Merge branch 'master' into translation-jp

pull/108/head
kenichiy 8 years ago
commit ba470565ad

6
.gitignore vendored

@ -5,3 +5,9 @@ tmp*.png
book.tex
book.pdf
log/*
/.idea
.idea/
idea/
/07/test.html
/appendix/04/index.html
/09/test.html

3
.gitmodules vendored

@ -7,3 +7,6 @@
[submodule "src/glslEditor"]
path = src/glslEditor
url = https://github.com/patriciogonzalezvivo/glslEditor.git
[submodule "src/glslGallery"]
path = src/glslGallery
url = https://github.com/patriciogonzalezvivo/glslGallery.git

@ -3,49 +3,49 @@
<canvas id="custom" class="canvas" data-fragment-url="cmyk-halftone.frag" data-textures="vangogh.jpg" width="700px" height="320px"></canvas>
上面两幅图由不同的方式制成。第一张是梵高用手一层一层画出来的,需要花费些时间。第二张则是用一些【?像素矩阵的组合】生成的:一个青色,一个品红,一个黄色,和一个黑色。关键的区别在于第二张图是用非序列方式实现的(即不是一步一步实现,而是多个同时进行)。
上面两幅图由不同的方式制成。第一张是梵高一层一层徒手画出来的,需要花费些时间。第二张则是用 4 个像素矩阵分秒钟生成的:一个青色,一个品红,一个黄色,和一个黑色矩阵。关键的区别在于第二张图是用非序列方式实现的(即不是一步一步实现,而是多个同时进行)。
这本书是关于这个革命性的计算机技术片段着色器fragment shaders它将数字生成的图像带到了新的层面。类似于当年古腾堡的印刷术。
这本书是关于这个革命性的计算机技术片段着色器fragment shaders它将数字生成的图像提到了新的层次。你可以把它看做当年的古腾堡印刷术。
![Gutenberg's press](gutenpress.jpg)
Fragment shaders片段着色器可以让你控制像素在屏幕上的快速渲染。这就是为什么 shader 在各种场合被广泛使用的原因不管是在手机的视频过滤器还是酷炫的的3D视频游戏中
Fragment shaders片段着色器可以让你控制像素在屏幕上的快速渲染。这就是它在各种场合被广泛使用的原因从手机的视频滤镜到酷炫的的3D视频游戏
![Journey by That Game Company](journey.jpg)
在接下来的章节你会发现 shader 是多么难以置信地快速和强大,还有如何将它应用到专业的和个人的作品中。
在接下来的章节你会发现这项技术是多么难以置信地快速和强大,还有如何将它应用到专业的和个人的作品中。
## 这本书是为谁而写的?
这本书是写给有线性代数和三角学的基本知识的创意编程者、游戏开发者和工程师的,还有那些想要提升他们的作品的图质量到一个令人激动的新层次的人。(如果你想要学习编程,我强烈推荐你先学习[Processing](https://processing.org/)等你玩起来processing再回来看这个
这本书是写给有代码经验和线性代数、三角学的基本知识的创意编程者、游戏开发者和工程师的,还有那些想要提升他们的作品的图质量到一个令人激动的新层次的人。(如果你想要学习编程,我强烈推荐你先学习[Processing](https://processing.org/)等你玩起来processing再回来看这个
这本书会教你如何使用shaders并把它整合进你的项目里以提升作品的表现力和图形质量。因为GLSLOpenGL的绘制语言的shaders 在很多平台都可以编译和运行你将可以把在这里学的运用到任何使用OpenGL, OpenGL ES 和 WebGL 的环境中。也就是说,你将可以把学到的知识应用到[Processing](https://processing.org/)[openFrameworks](http://openframeworks.cc/)[Cinder](http://libcinder.org/)[Three.js](http://threejs.org/)和iOS/Android游戏中。
这本书会教你如何使用 shaders(着色器)并把它整合进你的项目里以提升作品的表现力和图形质量。因为GLSLOpenGL的绘制语言的shaders 在很多平台都可以编译和运行你将可以把在这里学的运用到任何使用OpenGL, OpenGL ES 和 WebGL 的环境中。也就是说,你将可以把学到的知识应用到[Processing](https://processing.org/)[openFrameworks](http://openframeworks.cc/)[Cinder](http://libcinder.org/)[Three.js](http://threejs.org/)和iOS/Android游戏中。
## 这本书包含哪些内容?
这本书将会专注于GLSL像素着色。首先我们会给出shaders的定义然后我们会学习如何制作可被程序执行的形状,图案,材质,和与之相关的动画。你将会学到基础的着色语言并把它们应用到有用的情景中,比如:图像加工图像运算矩阵卷积模糊颜色过滤查找表及其他效果和模拟Conway的生命游戏Gray-Scott反应扩散水波水彩效果Voronoi细胞等等。到书的最后我们讲看到一系列基于光线行进的进阶技术。
这本书专门关于 GLSL pixel shaders。首先我们会给出shaders的定义然后我们会学习如何制作程序里的形状,图案,材质,和与之相关的动画。你将会学到基础的着色语言并把它们应用到有用的情景中,比如:图像处理图像运算矩阵卷积模糊颜色滤镜查找表及其他效果和模拟Conway 的生命游戏Gray-Scott 反应扩散水波水彩效果Voronoi 细胞等等。到书的最后我们将看到一系列基于光线跟踪Ray Marching的进阶技术。
**每章都会有可以玩的交互的例子。**当你改动代码的时候,你会立刻看到这些变化。一些概念可能会晦涩难懂,而这些可交互的例子会对你学习这些材料非常有益。你越快把这些代码付诸实践,你学习的过程就会越容易。
这本书里不包括的内容有:
* 这**不是**一本openGL或webGL的书。OpenGL/webGL是一个比GLSL或fragment shaders更大的主题。如果你想要学习openGL/webGL推荐看 [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)
* 这**不是**一本 openGL webGL 的书。OpenGL/webGL 是一个比GLSL fragment shaders 更大的主题。如果你想要学习 openGL/webGL 推荐看: [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的浏览器像ChromeFirefox或Safari和网络点击页面底端的“下一章”按钮就可以开始了。
没什么。如果你有可以运行 WebGL 的浏览器像ChromeFirefox或Safari和网络点击页面底端的“下一章”按钮就可以开始了。
此外,基于你有的条件或需求你可以:
* [制作一个离线版的本书](http://thebookofshaders.com/appendix/)
* [制作一个离线版的本书](https://thebookofshaders.com/appendix/)
* [用树莓派而不是浏览器来运行书中示例](http://thebookofshaders.com/appendix/)
* [用树莓派而不是浏览器来运行书中示例](https://thebookofshaders.com/appendix/)
* [做一个PDF版的书用于打印](http://thebookofshaders.com/appendix/)
* [做一个PDF版的书用于打印](https://thebookofshaders.com/appendix/)
* 用[github仓库](https://github.com/patriciogonzalezvivo/thebookofshaders)来帮助解决问题和分享代码

@ -39,10 +39,10 @@ Que cosas no vas a encontrar en este libro:
Alternativamente, dependiendo cuales sean tus necesidades puedes:
- [Crear una versión offline del libro](http://thebookofshaders.com/appendix/)
- [Crear una versión offline del libro](https://thebookofshaders.com/appendix/)
- [Correr los ejemplos en una RaspberryPI sin un navegador](http://thebookofshaders.com/appendix/)
- [Correr los ejemplos en una Raspberry Pi sin un navegador](https://thebookofshaders.com/appendix/)
- [Crear un PDF del libro para imprimir.](http://thebookofshaders.com/appendix/)
- [Crear un PDF del libro para imprimir.](https://thebookofshaders.com/appendix/)
- Usar el [repositorio on-line](https://github.com/patriciogonzalezvivo/thebookofshaders) y ayudarnos a resolver problemas y compartir código.

@ -1,48 +1,60 @@
# Introduction
# Introduction
<canvas id="custom" class="canvas" data-fragment-url="cmyk-halftone.frag" data-textures="vangogh.jpg" width="700px" height="320px"></canvas>
Les images au-dessus ont été faites de différentes manières. La première a été peinte à la main par Van Gogh, couche après couche. Cela lui a pris des heures. La deuxième a été produite en quelques secondes par la combinaison de quatre matrices de pixels: une pour le cyan, une pour le magenta, une pour le jaune et une pour le noir. La principale différence est que la seconde image n'a pas été produite de manière sérielle (c'est-à-dire non étape par étape, mais tout en même temps).
Les images ci-dessus ont été crées de différentes manières.
La première est un tableau de Van Gogh, réalisée en appliquant des couches de peinture successives.
ça lui a pris des jours, voire des semaines.
La seconde est réalisée en temps réel en combinant 4 matrices de pixels ; une pour le cyan, une pour le magenta, une pour le jaune et une pour le noir.
La différence principale entre ces deux images (hormis le medium), est que la seconde n'est pas sérielle ; elle n'est pas créée par étapes successives mais d'un bloc grâce à un shader.
Ce livre traite de la technique informatique révolutionnaire, les *fragment shaders*, qui élargissent les possibilités de la génération d'images numériques. Vous pouvez le voir comme l'équivalent de la naissance de l'imprimerie par Gutenberg, mais pour la fabrication d'image.
Ce livre parle d'une technique, les *shaders*, qui permet à l'imagerie numérique de s'affranchir de la plupart des contraintes.
On peut comparer l'avènement des *shaders* à l'avancée qu'a représenté la presse de Guntenberg à son époque.
![Gutenberg's press](gutenpress.jpg)
![la presse de Gutenberg](gutenpress.jpg)
Les fragment shaders vous donnent un contrôle total sur les pixels générés à l'écran et ceci à une très grande vitesse. C'est pourquoi ils sont utilisés dans toutes sortes de cas, depuis les filtres vidéos sur téléphone aux époustouflants jeux vidéos en 3D.
Les shaders donnent un contrôle total sur les pixels de l'écran à une vitesse très élevée.
c'est pourquoi ils sont utilisés dans une grande variété de domaines allant des filtres photo et vidéo, aux téléphones mobiles jusqu'aux jeux vidéos 3D.
![Journey by That Game Company](journey.jpg)
![Journey par That Game Company](journey.jpg)
Dans les chapitres suivants, vous allez découvrir à quel point cette technique est incroyablement rapide et puissante et comment l'appliquer à votre travail personnel et professionnel.
Au fil des chapitres, vous découvrirez combien les shaders sont efficaces et comment vous pourrez vous en servir pour vos projets personnels et/ou professionnels.
## A qui s'adresse ce livre?
## à qui s'adresse ce livre?
Ce livre est écrit pour les codeurs créatifs, les développeurs de jeux et ingénieurs qui ont une expérience de la programmation, des connaissances de base en algèbre linéaire et en trigonométrie, et qui veulent pousser leur travail afin d'atteindre un niveau de qualité graphique encore plus palpitant. (Si vous voulez apprendre à programmer, je vous recommande vivement de commencer avec [Processing](https://processing.org/) et de revenir plus tard lorsque vous vous sentirez à l'aise avec la programmation.)
Ce livre est écrit pour les *creative coders*, les développeurs de jeux, les ingénieurs et les curieux ayant un bagage de code, des connaissances basiques en algèbre linéaire et en trigonométrie et désireux d'améliorer la qualité graphique de leurs productions.
Si vous n'avez aucune connaissance en code, nous vous recommandons chaudement de commencer par [Processing](https://processing.org/) puis de revenir à ce livre lorsque vous vous sentirez plus à l'aise.
Ce livre va vous apprendre comment utiliser et intégrer les shaders dans vos projets, en améliorant leur performance et leur qualité graphique. Parce que les shaders GLSL (OpenGL Shading Language) compilent et s'exécutent sur un grand nombre de plateformes, vous serez à même de déployer vos connaissances sur des sketches [Processing](https://processing.org/), des applications [openFrameworks](http://openframeworks.cc/), des installations interactives [Cinder](http://libcinder.org/), des sites avec [Three.js](http://threejs.org/) ou des jeux sous iOS/Android.
Ce livre vous montrera comment utiliser et intégrer des shaders dans vos projets, comment améliorer leurs performances et leur rendu graphique.
Du fait que les shaders GLSL (OpenGL Shading Language) peuvent être compilés sur diverses plateformes, il vous sera possible de réutiliser ce que vous aurez appris ici dans n'importe quel environnement utilisant OpenGL, OpenGL ES ou WebGL. Autrement dit, vous pourrez réutiliser vos connaissances sur des plateformes comme [Processing](https://processing.org/), [openFrameworks](http://openframeworks.cc/), [Cinder](http://libcinder.org/), [Three.js](http://threejs.org/) ou iOS et Android.
## De quoi traite ce livre?
## que contient ce livre?
Ce livre se concentrera sur l'utilisation des pixel shaders GLSL. Dans un premier temps, nous définirons ce que sont les shaders; puis nous apprendrons comment, grâce à eux, faire des formes procédurales, des motifs, des textures et des animations. Vous apprendrez les bases du langage des shaders et l'appliquerez à des scénarios plus utiles comme: le traitement d'images (les opérations sur les images, les matrices de convolution, les flous, les filtres de couleur, les tables de correspondances et autres effets) et les simulations (le jeu de la vie imaginé par John H. Conway, le système à réaction-diffusion de Gray-Scott, les ondulations à la surface de l'eau, les effets aquarelle, les diagrammes de Voronoï, etc). A la fin de ce livre, nous verrons un ensemble de techniques avancées basées sur le Ray Marching.
Ce livre se concentre sur l'utilisation des Fragment Shaders.
nous définirons ce que sont les shaders, puis nous apprendrons à dessiner des formes, des textures et des motifs procéduraux (à base d'instructions mathématiques).
nous apprendrons les bases du langage de shading avant de les utiliser sur des cas concrets comme le traitement d'image (transformations, convolution, flou, filtres et autres effets), les simulations (le jeu de la vie de Conway, la réaction diffusion de Gray-Scott, les vaguelettes sur un plan d'eau, les cellules de Voronoi, etc. ), enfin nous aborderons les techniques avancées basées sur le Ray Marching.
*Dans chaque chapitre, des exemples interactifs vous permettront de vous amuser avec les concepts traités. *Lorsque vous modifierez le code, le résultat de ces changements sera visible instantanément. Certains concepts peuvent être abstaits et déroutants, dans ce cas les exemples interactifs sont les bienvenus pour vous aider à comprendre les informations. Le plus vite vous mettrez ces concepts en mouvement, le plus simple sera votre apprentissage.
Ce dont ne traite pas ce livre:
*Chaque chapitre comporte des exemples interactifs, n'hésitez pas à jouer avec!* lorsque vous changez le code des exemples, le shader est recompilé et - s'il est valide - vous verrez le résultat instantanément. Les concepts paraîssent souvent abstraits et peuvent laisser perplexe donc les exemples sont là pour vous aider à mieux comprendre ce qui se passe. nous sommes partisans de l'apprentissage par l'exemple, n'hésitez pas à vous approprier les exemples, quitte à les casser (plusieurs fois s'il le faut).
* Ce *n'est pas* un livre sur openGL ou webGL. OpenGL/webGL est un sujet plus vaste que GLSL ou les fragment shaders. Pour en apprendre plus sur OpenGL/webGL, je vous recommande de jeter un oeil sur: [OpenGL Introduction](https://open.gl/introduction), [la 8ème édition du 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) (aka le livre rouge) 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 que ce livre n'est pas:
* Ce *n'est pas* un livre de maths. Bien que nous couvrirons certains algorithmes et certaines techniques reposant sur la compréhension de l'algèbre et la trigonométrie, nous ne les expliquerons pas en détail. Pour ce qui concerne les mathématiques, je recommande de garder près de vous un des ouvrages suivant: [La 3ème édition de 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 [La 2ème édition de 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).
* 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)
## De quoi avez-vous besoin pour commencer?
* 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).
Pas grand-chose! Si vous avez un navigateur moderne qui supporte WebGL (comme Chrome, Firefox ou Safari) et une connexion internet, cliquez sur le bouton du chapitre suivant en bas de page pour commencer.
## bien démarrer
Sinon, au vu de ce que vous avez ou de ce que vous avez besoin pour ce livre, vous pouvez:
si vous avez un navigateur récent (comme chrome, firefox ou safari) et une connection internet, il vous suffira de cliquer sur "suivant" en bas de page pour commencer l'aventure.
- [Faire une version hors-ligne de ce livre](http://thebookofshaders.com/appendix/)
Cela étant et selon ce que vous voulez faire de ce livre, vous pouvez :
- [Exécuter les exemples sur un RaspberryPi sans navigateur](http://thebookofshaders.com/appendix/)
- [créer une copie locale de ce livre pour le consulter hors-ligne](https://thebookofshaders.com/appendix/)
- [Faire un PDF de ce livre pour impression](http://thebookofshaders.com/appendix/)
- [lancer les exemples directement sur Raspberry Pi, sans navigateur](https://thebookofshaders.com/appendix/)
- Utiliser le [répertoire github](https://github.com/patriciogonzalezvivo/thebookofshaders) afin d'aider à résoudre des problèmes et de partager du code.
- [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.

@ -0,0 +1,50 @@
# Introduzione
<canvas id="custom" class="canvas" data-fragment-url="cmyk-halftone.frag" data-textures="vangogh.jpg" width="700px" height="320px"></canvas>
Le immagini qui sopra sono state realizzate in modi diversi. La prima è stata dipinta a mano da Van Gogh, aggiungendo strati di pittura uno dopo l'altro. Gli ci vollero ore. La seconda è stata prodotta in qualche secondo dalla combinazione di quattro matrici di pixel: una per il ciano, una per il magenta, una per il giallo e una per il nero. La differenza principale è che la seconda immagine è prodotta in modo non seriale (cioè non passo-passo, ma tutta allo stesso tempo).
Questo libro tratta della tecnica di calcolo rivoluzionario, i *fragment shaders*, che sta portando a un livello successivo le immagini generate digitalmente. Lo si può pensare come l'equivalente della stampa di Gutenberg per la grafica.
![Stampa di Gutenberg](gutenpress.jpg)
I fragment shaders danno un controllo totale sui pixel, che sono resi sullo schermo a una super velocità. Questo è il motivo per cui sono utilizzati in molteplici applicazioni, dai filtri video sui cellulari ad incredibili videogiochi 3D.
![Journey di That Game Company](journey.jpg)
Nei capitoli seguenti scopriremo quanto veloce e potente sia questa tecnica e come poterla applicare al vostro lavoro professionale e personale.
## Per chi è questo libro?
Questo libro è scritto per programmatori creativi, sviluppatori di giochi e ingegneri che hanno esperienza di programmazione, una conoscenza di base di algebra lineare e di trigonometria, e che vogliono portare il loro lavoro ad un livello di qualità grafica ancora più emozionante. (Se si vuole imparare a programmare, vi raccomando di iniziare con [Processing](https://processing.org/) e tornare più tardi, quando avrete maggiore dimestichezza.)
Questo libro vi insegnerà come utilizzare e integrare shader nei vostri progetti, migliorando le loro prestazioni e la qualità grafica. Poiché gli GLSL (OpenGL Shading Language) shaders compilano e si eseguono su una grande varietà di piattaforme, si potrà applicare ciò che si impara qui a qualsiasi framework che utilizza OpenGL, OpenGL ES o WebGL. In altre parole, si sarà in grado di applicare e utilizzare la propria conoscenza negli sketches di [Processing](https://processing.org/), nelle applicazioni di [openFrameworks](http://openframeworks.cc/), nelle installazioni interattive di [Cinder](http://libcinder.org/), nei siti web con [Three.js](http://threejs.org/) o nei giochi iOS / Android.
## Di che cosa tratta questo libro?
Questo libro si concentrerà su l'uso dei pixel shaders GLSL. Per prima cosa definiremo cosa sono gli shaders; poi impareremo come fare, grazie a loro, forme procedurali, motivi, texture e animazioni. Imparerete le basi del linguaggio shading ed ad applicarlo a scenari più utili, quali: l'elaborazione di immagini (operazioni di immagine, circonvoluzioni di matrice, sfocature, filtri colorati, tabelle di associazione e altri effetti) e simulazioni (il gioco della vita di Conway, la reazione-diffusione di Gray-Scott, le increspature d'acqua, gli effetti acquerello, le celle di Voronoi, etc.). Verso la fine del libro vedremo un insieme di tecniche avanzate basate sul Ray Marching.
*In ogni capitolo, ci sono degli esempi interattivi per imparare divertendosi. * Quando si modifica il codice, vedrete immediatamente sullo schermo i cambiamenti. I concetti possono essere astratti e confusi, perciò gli esempi interattivi sono essenziali per aiutarvi a capire gli argomenti trattati. Più velocemente i concetti si mettono in pratica e più facilmente si imparerà.
Di cosa non tratta questo libro:
* Questo * non è * un libro su OpenGL o WebGL. OpenGL / WebGL è un soggetto più vasto di GLSL o dei fragment shaders. Per ulteriori informazioni su OpenGL / WebGL vi consiglio di dare un'occhiata a: [OpenGL Introduzione](https://open.gl/introduction), [l'ottava edizione della guida sulla programmazione OpenGL](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) (noto anche come il libro rosso) o [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).
* Questo * non è* un libro di matematica. Anche se ci occuperemo di una serie di algoritmi e di tecniche che si basano su una comprensione dell'algebra e della trigonometria, non spiegheremo tutto in dettaglio. Per domande riguardanti la matematica vi consiglio di tenere vicino uno dei seguenti libri: [La terza edizione di Matematica per la programmazione di giochi 3D e la computer Grafica](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) o [La seconda edizione di Matematica Essenziale per Giochi e Applicazioni Interattive](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).
## Cosa ti serve per iniziare?
Non tanto! Se si dispone di un browser moderno che può far girare WebGL (come Chrome, Firefox o Safari) e una connessione Internet, fai clic sul bottone "Next" alla fine di questa pagina per iniziare.
In alternativa, in base a ciò di cui avete bisogno, è possibile:
- [Creare versione offline di questo libro](https://thebookofshaders.com/appendix/)
- [Eseguire gli esempi su un Raspberry Pi senza navigatore](https://thebookofshaders.com/appendix/)
- [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.

@ -46,10 +46,10 @@ Chrome、FirefoxやSafariなどWebGLの使える今時のブラウザーとイ
もし必要な場合は下記もご覧ください。(訳注:いまのところ英語のみです。そのうち翻訳します)
- [Make an off-line version of this book](http://thebookofshaders.com/appendix/)
- [Make an off-line version of this book](https://thebookofshaders.com/appendix/)
- [Run the examples on a RaspberryPi without a browser](http://thebookofshaders.com/appendix/)
- [Run the examples on a Raspberry Pi without a browser](https://thebookofshaders.com/appendix/)
- [Make a PDF of the book to print](http://thebookofshaders.com/appendix/)
- [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.

@ -38,11 +38,11 @@ Fragment shader는 매우 빠른 속도로 스크린에 렌더되는 픽셀들
아니면 , 다음과 같은 방법으로도 이 책을 접할수 있다:
- [이책의 오프라인 버젼](http://thebookofshaders.com/appendix/)
- [이책의 오프라인 버젼](https://thebookofshaders.com/appendix/)
- [RaspberryPi에서 브라우져 없이 예제들 돌리기](http://thebookofshaders.com/appendix/)
- [Raspberry Pi에서 브라우져 없이 예제들 돌리기](https://thebookofshaders.com/appendix/)
- [이책의 PDF버젼 만들기](http://thebookofshaders.com/appendix/)
- [이책의 PDF버젼 만들기](https://thebookofshaders.com/appendix/)
- 또는 [온라인 리포](https://github.com/patriciogonzalezvivo/thebookofshaders) 이슈들을 답하거나, 올려주세요.

@ -38,11 +38,11 @@ Not much! If you have a modern browser that can do WebGL (like Chrome, Firefox o
Alternatively, based on what you have or what you need from this book you can:
- [Make an off-line version of this book](http://thebookofshaders.com/appendix/)
- [Make an off-line version of this book](https://thebookofshaders.com/appendix/)
- [Run the examples on a RaspberryPi without a browser](http://thebookofshaders.com/appendix/)
- [Run the examples on a Raspberry Pi without a browser](https://thebookofshaders.com/appendix/)
- [Make a PDF of the book to print](http://thebookofshaders.com/appendix/)
- [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.

@ -0,0 +1 @@
# Introduction

Binary file not shown.

Before

Width:  |  Height:  |  Size: 344 KiB

After

Width:  |  Height:  |  Size: 338 KiB

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

@ -7,7 +7,7 @@
如果你曾经有用计算机绘图的经验,你就知道在这个过程中你需要画一个圆,然后一个长方形,一条线,一些三角形……直到画出你想要的图像。这个过程很像用手写一封信或一本书 —— 都是一系列的指令,需要你一件一件完成。
Shaders 也是一系列的指令,但是这些指令会对屏幕上的每个像素同时下达。也就是说,你的代码必须根据像素在屏幕上的不同位置,表现出不同的样貌。就像活字印刷,你的程序就像一个 function函数输入位置信息输出颜色信息当它编译完之后会以相当快的速度运行。
Shaders 也是一系列的指令,但是这些指令会对屏幕上的每个像素同时下达。也就是说,你的代码必须根据像素在屏幕上的不同位置执行不同的操作。就像活字印刷,你的程序就像一个 function函数输入位置信息输出颜色信息当它编译完之后会以相当快的速度运行。
![Chinese movable type](typepress.jpg)
@ -15,7 +15,7 @@ Shaders 也是一系列的指令,但是这些指令会对屏幕上的每个像
为了回答这个问题,不得不给大家介绍**并行处理**parallel processing的神奇之处。
想象你的 CPU 是一个大的工业管道,然后每一个任务都是通过这个管道的某些东西 —— 就像一个生产流水线那样。有些任务要比别的大,也就是说要花费更多时间和精力去处理。我们就称它要求更强的处理能力。因为计算机自身架构的原因,这些任务需要串行;即一次一个地依序完成。现代计算机通常有一组四个处理器,就像这个管道一样运行,一个接一个地处理这些任务,从而使计算机流畅运行。每个管道通常被称为**线程**。
想象你的 CPU 是一个大的工业管道,然后每一个任务都是通过这个管道的某些东西 —— 就像一个生产流水线那样。有些任务要比别的大,也就是说要花费更多时间和精力去处理。我们就称它要求更强的处理能力。由于计算机自身的架构,这些任务需要串行;即一次一个地依序完成。现代计算机通常有一组四个处理器,就像这个管道一样运行,一个接一个地处理这些任务,从而使计算机流畅运行。每个管道通常被称为**线程**。
![CPU](00.jpeg)
@ -35,14 +35,14 @@ Shaders 也是一系列的指令,但是这些指令会对屏幕上的每个像
## GLSL是什么
GLSL 代表 openGL Shading LanguageopenGL 着色语言这是你在接下来章节看到的程序所遵循的具体标准。根据硬件和操作系统的不同还有其他的着色器shaders)。这里我们将依照[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 LanguageopenGL 着色语言这是你在接下来章节看到的程序所遵循的具体标准。根据硬件和操作系统的不同还有其他的着色器shaders)。这里我们将依照[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)。
## 为什么 Shaders 有名地不好学?
就像蜘蛛侠里的那句名言,欲戴其冠必承其重并行计算也是如此GPU 的强大的架构设计也有其限制与不足。
就像蜘蛛侠里的那句名言,能力越大责任越大并行计算也是如此GPU 的强大的架构设计也有其限制与不足。
为了能使许多管线并行运行,每一个线程必须与其他的相独立。我们称这些线程对于其他线程在进行的运算是“盲视”的。这个限制就会使得所有数据必须以相同的方向流动。所以就不可能检查其他线程的输出结果,修改输入的数据,或者把一个线程的输出结果输入给另一个线程。如果允许线程到线程的数据流动将使所有的数据面临威胁。
并且 GPU 会让所有并行的微处理器(管道们)一直处在忙碌状态;只要它们一有空闲就会接到新的信息。一个线程不可能知道它前一刻在做什么。它可能是在画操作系统界面上的一个按钮,然后渲染了游戏中的一部分天空,然后显示了一封 email 中的一些文字。每个线程不仅是“盲视”的,而且还是“无记忆”的。同时,它要求编写一个通用的规则,依据像素的不同位置依次输出不同的结果。这种抽象性,和盲视、无记忆的限制使得 shaders 在程序员新中不是很受欢迎。
并且 GPU 会让所有并行的微处理器(管道们)一直处在忙碌状态;只要它们一有空闲就会接到新的信息。一个线程不可能知道它前一刻在做什么。它可能是在画操作系统界面上的一个按钮,然后渲染了游戏中的一部分天空,然后显示了一封 email 中的一些文字。每个线程不仅是“盲视”的,而且还是“无记忆”的。同时,它要求编写一个通用的规则,依据像素的不同位置依次输出不同的结果。这种抽象性,和盲视、无记忆的限制使得 shaders 在程序员新中不是很受欢迎。
但是不要担心!在接下来的章节中,我们会一步一步地,由浅入深地学习着色语言。如果你是在用一个靠谱的浏览器阅读这个教程,你会喜欢边读边玩书中的示例的。好了,不要再浪费时间了,赶快去玩起来吧! 点击**Next >>**开启 shader 之旅!
但是不要担心!在接下来的章节中,我们会一步一步地,由浅入深地学习着色语言。如果你是在用一个靠谱的浏览器阅读这个教程,你会喜欢边读边玩书中的示例的。好了,不要再浪费时间了,赶快去玩起来吧! 点击 **Next >>** 开启 shader 之旅!

@ -0,0 +1,84 @@
# bien démarrer
## qu'est-ce qu'un fragment shader?
Au chapitre précédent, nous avons décrit les shaders comme l'équivalent de l'avènement de la presse par Gutenberg pour l'impression. Pourquoi cette comparaison mais surtout: Qu'est-ce qu'un shader?
![de la copie manuelle, lettre à lettre, à l'édition page à page (gauche: William Blades 1891, droite: Rolt-Wheeler 1920)](print.png)
Si vous avez déjà dessiné avec un ordinateur, vous savez qu'il faut dessiner un cercle, puis un rectangle, une ligne, quelques triangles jusqu'à pouvoir composer l'image qu'on veut.
Ce processus est très similaire à l'écriture d'une lettre ou d'un livre voire à la peinture, c'est un ensemble d'instructions, exécutées en série, l'une après l'autre.
Les shaders sont également des ensembles d'instructions, mais à la différence des API de dessin classiques, *toutes les instructions sont exécutées sur chaque pixel de l'écran*.
Cela signifie que le code va devoir se comporter différemment selon la position du pixel à l'écran.
Comme la presse d'imprimerie, le fragment shader est une fonction à laquelle on passe une position et qui nous renvoie une couleur.
Une fois _compilé_, ce programme peut s'exécuter extrêmement rapidement.
![presse chinoise à caractères amovibles](typepress.jpg)
## Pourquoi sont-ils si rapides?
La réponse est le *traitement parallèle*.
Imaginez le CPU de votre ordinateur comme un *tuyau* et chacune des tâches que vous lui demandez d'exécuter comme *quelque chose* qui passe par ce tuyau, comme dans une usine.
Certaines tâches seront sans doute plus importantes que d'autres, elles demanderont plus de temps et d'énergie pour être traitées, on dit qu'elles nécessitent plus de ressources ou de puissance de calcul.
Du fait de l'architecture des ordinateurs, les tâches sont traitées en série ; chaque tâche doit être terminée avant que le CPU puisse traiter la suivante.
Les ordinateurs récents ont généralement plusieurs processeurs qui jouent le rôle de *tuyaux*, ce qui permet d'enchaîner les tâches en série tout en gardant une certaines fluidité, ces tuyaux s'appellent des *threads*.
![CPU](00.jpeg)
Les jeux vidéos et autres applications graphiques demandent beaucoup plus de puissance de calcul que les autres programmes.
Par nature, ils demandent de grandes quantités d'opérations au pixel, chaque changement d'image demandent de recalculer l'ensemble des pixels de l'écran.
Dans les applications 3D, on doit également mettre à jour les modèles, les textures, les transformations etc. ce qui rajoute encore du poids à la charge CPU.
Revenons à notre métaphore des tuyaux et des tâches où:*"trouver la couleur d'un pixel à l'écran"* représente une petite tâche toute simple.
En soi, chaque tâche n'est pas bien méchante mais il faut l'appliquer sur chaque pixel de l'écran! et c'est là que ça se corse ; il nous faut à présent exécuter cette petite opération un nombre considérable de fois.
Par exemple pour exécuter l'ensemble des tâches permettant de dessiner l'ensemble des pixels d'un vieux moniteur ayant une résolution de 800 x 600 pixels, il faut compter 800 x 600 = 480.000 appels à cette petite tâche.
Ces 480.000 appels ne valent que pour dessiner une seule frame, si on veut animer notre écran à 30 images/seconde pendant une seconde, il nous en coûtera 11.520.000 appels et si on veut du 60fps, on passe à 28.800.000 de tâches à traiter.
Peut-être que le problème est plus facile à identifier lorsqu'on commence à parler de dizaines de millions d'opérations/seconde, si on prend une configuration moderne, 2880/1800 pixels devant tourner à 60 fps, on atteint 311.040.000 calculs / seconde.
des centaines de millions d'opérations par seconde, ce sont des quantités propres à freezer voire à détruire un microprocesseur. alors comment fait-on?
![](03.jpeg)
C'est là qu'intervient le traitement parallèle (parallel processing).
Au lieu d'avoir quelques gros *tuyaux* (microprocesseurs), on préfère avoir de nombreux petits microprocesseurs qui tournent en parallèle et simultanément, c'est l'essence du GPU: Graphics Processing Unit.
![GPU](04.jpeg)
Imaginez ces petits microprocesseurs comme une trame de tuyaux, et les données de chaque pixel comme des balles de pingpong.
14.400.000 balles de pingpong par secondes pourraient boucher à peu près n'importe quel tuyau.
Mais une trame de 800 * 600 (480.000) petits tuyaux recevant 30 vagues de 480.000 balles de pingpong par secondes peuvent traiter la charge facilement.
Et ça marche pour des résolutions plus élevées ; plus le matériel est capable de traiter d'informations en parallèle, plus il pourra traiter des flux importants.
Un autre pouvoir magique des GPU c'est l'accélération matérielle de certaines fonctions mathématiques.
Certaines fonctions souvent un peu complexes seront traitées directement par le matériel au lieu de passer par la couche logicielle.
Ce qui signifie que certaines opérations mathématiques un peu complexes comme les transformations de matrics et les opérations trigonométriques seront traitées très vite, en fait, à la vitesse de l'électricité.
## qu'est ce que le GLSL?
GLSL est l'acronyme de 'openGL Shading Language' (où GL signifie Graphics Library), c'est une norme servant à écrire les programmes de shaders que nous aborderons dans les chapitres suivants.
Il existe d'autres types de shaders, selon les plateformes et le matériel utilisé, nous nous concentrerons sur l'OpenGL, dont les spécifications sont faites par le [Khronos Group](https://www.khronos.org/opengl/).
Comprendre l'histoire d'OpenGL peut être utile pour comprendre certaines conventions un peu bizarres, si ça vous intéresse, vous pouvez vous reporter à [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html).
## Pourquoi les gens tremblent en entendant le mot Shader?
Comme dit *Uncle Ben* dans Spiderman: "with great power comes great responsibility" ([merci à Nicolas Gans](https://en.m.wikipedia.org/wiki/Uncle_Ben)), le traitement parallèle ne déroge pas à cette règle et aussi puissante que soit la programmation GPU, elle apporte un cortège de contraintes et de restrictions.
Pour pouvoir travailler avec une *trame* de *threads*, il faut que chaque thread soit indépendant des autres. On dit que le thread est *aveugle* à ce que font les autres threads.
Cette restriction implique que toutes les données doivent aller dans le même sens, il est donc impossible de se servir ou simplement de connaître les résultat d'un autre thread.
Autoriser la communication entre threads au moment de l'exécution pourrait compromettre l'intégrité des données en cours de traitement.
Il faut également savoir que le GPU s'assure que tous ses microprocesseurs (la *trame de threads*) sont actifs en permanence ; dès qu'un thread a fini son traitement, le GPU lui ré-assigne une tâche à traiter.
Le thread ne garde aucune trace de ce qu'il faisait la fois précédente ; s'il était en train de dessiner un le pixel d'un bouton sur une interface graphique, sa tâche suivante pourra être de rendre un bout du ciel dans un jeu, puis de rendre un bout de texte sur un client mail etc.
Donc un thread est non seulement **aveugle** mais aussi **amnésique**
En plus du niveau d'abstraction élevé requis pour coder une fonction générique qui saura rendre une image entière uniquement à partir de la variation d'une position, les deux contraintes des threads, **aveuglement** et **amnésie** rendent la programmation de shaders assez impopulaire auprès des programmeurs débutants.
Mais n'ayez crainte! au cours des chapitres suivants, nous abordons les problèmes étape par étape et passerons d'un simple shader à des calculs avancés.
Si vous lisez ceci dans un navigateur récent, vous apprécierez de pouvoir manipuler les exemples interactifs et beaucoup de ce qui vient d'être dit s'éclairera de soi même.
Sans plus attendre, jetons nous dans le vif du sujet.
appuyez sur *Next >>* pour commencer!

@ -0,0 +1,48 @@
# Introduzione
## Che cosa è un fragment shader?
Nel capitolo precedente abbiamo descritto lo shader come l'equivalente della stampa di Gutenberg per la grafica. Perché? O meglio ancora: che cosa è uno shader?
![From Letter-by-Letter, Right: William Blades (1891). To Page-by-page, Left: Rolt-Wheeler (1920).](print.png)
Se hai già fatto disegni al computer, saprai che si inizia disegnando un cerchio, poi un rettangolo, una linea, alcuni triangoli fino a comporre l'immagine desiderata. Questo processo è molto simile a scrivere una lettera o un libro a mano - in altre parole è un insieme di istruzioni, che eseguono un compito uno dopo l'altro.
Gli shaders si possono considerare allo stesso modo un insieme di istruzioni, che sono eseguite tutte nello stesso momento per ogni singolo pixel sullo schermo. Ciò significa che il codice scritto deve comportarsi in modo diverso a seconda della posizione del pixel sullo schermo. Come nel processo della pressa tipografica, il tuo programma riceverà una posizione e restituirà un colore. Quando il codice è compilato, verrà eseguito a velocità straordinaria.
![Pressa tipografica cinese](typepress.jpg)
## Perché gli shaders sono così veloci?
Per rispondere a questa domanda, vi presento le meraviglie del *calcolo parallelo*.
Immaginate la CPU del computer come un grande tubo industriale, e ogni compito come qualcosa che passa attraverso di esso - come in una linea di produzione. Alcuni compiti sono più grandi di altri, il che significa che richiedono più tempo ed energia. Diciamo che necessitano una maggiore potenza di elaborazione. A causa dell'architettura dei computer alcuni compiti sono costretti ad essere eseguiti in serie; ogni compito deve essere completato, uno dopo l'altro. I computer moderni hanno solitamente gruppi di quattro processori che funzionano come questi tubi, eseguendo i compiti uno dopo l'altro per avere le cose funzionanti senza intoppi. Ogni tubo è anche conosciuto come *thread*.
![CPU](00.jpeg)
I videogiochi e le altre applicazioni grafiche richiedono molta più potenza di elaborazione rispetto ad altri programmi. A causa del loro contenuto grafico devono fare un gran numero di operazioni per pixel. Ogni singolo pixel sullo schermo deve essere calcolato, e nei giochi 3D le geometrie e le prospettive devono essere calcolate allo stesso tempo.
Torniamo alla nostra metafora dei tubi e dei compiti. Ogni pixel sullo schermo rappresenta un piccolo compito da realizzare. Individualmente ogni compito non è un problema per la CPU, ma (e qui sta il problema) il piccolo compito deve essere fatto per ogni pixel sullo schermo! Ciò significa che in un vecchio schermo 800x600, 480000 pixel devono elaborati per frame cioè 14400000 calcoli al secondo! Si! Questo è un problema abbastanza grande capace di sovraccaricare un microprocessore. In un moderno schermo retina 2880x1800 in esecuzione a 60 fotogrammi al secondo si possono raggiungere fino a 311040000 calcoli al secondo. Come fanno gli ingegneri grafici a risolvere questo problema?
![](03.jpeg)
E' in questo caso che il calcolo parallelo diventa una buona soluzione. Invece di avere un paio di grandi e potenti microprocessori, o *tubi*, è più intelligente avere parecchi minuscoli microprocessori che funzionano in parallelo allo stesso tempo. Questo è la Graphic Processor Unit (GPU).
![GPU](04.jpeg)
Immaginate i minuscoli microprocessori come un tavolo di tubi, ed i dati di ciascun pixel come una pallina da ping pong. 14400000 palline da ping pong in un secondo possono ostacolare qualsiasi tubo. Ma un tavolo di 800x600 piccoli tubi che riceve 30 ondate di 480000 pixel al secondo si può gestire senza problemi. Tutto ciò funziona anche a risoluzioni più elevate - più si possiede hardware in parallelo, più grande è il flusso che si può gestire.
Un altro "super potere" della GPU è che alcune speciali funzioni matematiche sono accelerate via hardware, in modo tale che le operazioni matematiche complesse sono risolte direttamente dai microchip invece che da un software. Ciò significa che avremo una velocità extra nel calcolo trigonometrico e nelle operazioni fra matrici, una velocità pari a quella dell'elettricità.
## Che cosa è GLSL?
GLSL è l'acronimo di openGL Shading Language, che è lo standard specifico dei programmi shaders che vedrete nei prossimi capitoli. Ci sono altri tipi di shaders a seconda del hardware e dei sistemi operativi. Qui lavoreremo con le specifiche openGL regolate dal [Khronos Group](https://www.khronos.org/opengl/). Comprendere la storia di OpenGL può essere utile per capire la maggior parte delle sue strane convenzioni, per questo vi consiglio di dare un'occhiata a: [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html)
## Perché gli Shaders hanno notoriamente una brutta fama?
Come disse lo zio Ben "con un grande potere derivano grandi responsabilità", e il calcolo parallelo segue questa regola; la potente progettazione architettonica della GPU comporta specifici vincoli e restrizioni.
Affinché ogni tubo, o thread, venga eseguito in parallelo, è necessario che sia indipendente l'uno dall'altro. Diciamo i thread sono *ciechi* e non vedono ciò che gli altri thread stanno facendo. Questa restrizione implica che tutti i dati debbano affluire nella stessa direzione. Quindi è impossibile controllare il risultato di un altro thread, modificare i dati di input, o passare il risultato di un thread a un altro thread. Permettere la comunicazione fra thread metterebbe a rischio l'integrità dei dati.
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!

@ -0,0 +1,2 @@
# Getting started
## What is a fragment shader?

@ -1,3 +1,8 @@
### Scott M
* You say “pipes” and also “threads”. This is a small thing but I wonder if you can reconcile those metaphors. I think in terms of threads, but “pipes” makes more sense with your illustration. Also works better with the concept of a “pipeline” or “graphics/rendering pipeline”.
* You say “pipes” and also “threads”. This is a small thing but I wonder if you can reconcile those metaphors. I think in terms of threads, but “pipes” makes more sense with your illustration. Also works better with the concept of a “pipeline” or “graphics/rendering pipeline”.
### 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).

@ -2,7 +2,7 @@
“Hello world!”通常都是学习一个新语言的第一个例子。这是一个非常简单,只有一行的程序。它既是一个热情的欢迎,也传达了编程所能带来的可能性。
然而在 GPU 的世界里,第一步就渲染一行文字太难了,所以我们改为选择一个鲜艳的欢迎色,躁起来!
然而在 GPU 的世界里,第一步就渲染一行文字太难了,所以我们改为选择一个鲜艳的欢迎色,来吧躁起来!
<div class="codeAndCanvas" data="hello_world.frag"></div>
@ -10,15 +10,15 @@
尽管这几行简单的代码看起来不像有很多内容,我们还是可以据此推测出一些知识点:
1. shader 语言 有一个 ```main``` 函数会在最后返回颜色值。这点和C语言很像。
1. shader 语言 有一个 ```main``` 函数,会在最后返回颜色值。这点和 C 语言很像。
2. 最终的像素颜色取决于预设的全局变量 ```gl_FragColor```。
3. 这个C系语言有内建的**变量**(像```gl_FragColor```**函数**和**数据类型**。在本例中我们刚刚介绍了```vec4```(四分量浮点向量)。之后我们会见到更多的类型,像 ```vec3``` (三分量浮点向量)和 ```vec2``` (二分量浮点向量),还有非常著名的:```float```(单精度浮点型), ```int```(整型) 和 ```bool```(布尔型)。
3. 这个类 C 语言有内建的**变量**(像```gl_FragColor```**函数**和**数据类型**。在本例中我们刚刚介绍了```vec4```(四分量浮点向量)。之后我们会见到更多的类型,像 ```vec3``` (三分量浮点向量)和 ```vec2``` (二分量浮点向量),还有非常著名的:```float```(单精度浮点型), ```int```(整型) 和 ```bool```(布尔型)。
4. 如果我们仔细观察 ```vec4``` 类型,可以推测这四个变元分别响应红,绿,蓝和透明度通道。同时我们也可以看到这些变量是**规范化**的意思是它们的值是从0到1的。之后我们会学习如何规范化变量使得在变量间**map**(映射)数值更加容易。
5. 另一个可以从本例看出来的很重要的 C 语言特征是,预处理程序的宏指令。宏指令是预编译的一部分。有了宏才可以 ```#define``` (定义)全局变量和进行一些基础的条件运算(通过使用 ```#ifdef``` 和 ```#endif```)。所有的宏都以 ```#``` 开头。预编译会在编译前一刻发生,把所有的命令复制到 ```#defines``` 里,检查```#ifdef``` 条件句是否已被定义, ```#ifndef``` 条件句是否没有被定义。在我们刚刚的“hello world!”的例子中我们在第2行检查了 ```GL_ES``` 是否被定义,这个通常用在移动端或浏览器的编译中。
5. 另一个可以从本例看出来的很重要的 C 语言特征是,预处理程序的宏指令。宏指令是预编译的一部分。有了宏才可以 ```#define``` (定义)全局变量和进行一些基础的条件运算(通过使用 ```#ifdef``` 和 ```#endif```)。所有的宏都以 ```#``` 开头。预编译会在编译前一刻发生,把所有的命令复制到 ```#defines``` 里,检查```#ifdef``` 条件句是否已被定义, ```#ifndef``` 条件句是否没有被定义。在我们刚刚的“hello world!”的例子中我们在第2行检查了 ```GL_ES``` 是否被定义,这个通常用在移动端或浏览器的编译中。
6. ```float```类型在 shaders 中非常重要,所以**精度**非常重要。更低的精度会有更快的渲染速度,但是会以质量为代价。你可以选择每一个浮点值的精度。在第一行(```precision mediump float;```)我们就是设定了所有的浮点值都是中等精度。但我们也可以选择把这个值设为“低”(```precision lowp float;```)或者“高”(```precision highp float;```)。
@ -32,9 +32,9 @@ void main() {
现在我们已经基本讨论完了“hello world!”例子中所有主要的内容,是时候点击代码,检验一下我们所学的知识了。你会发现出错时程序会编译失败,只留一个寂寞的白屏。你可以试试一些好玩的小点子,比如说:
* 把单精度浮点值换成整型数值,猜猜你的显卡能不能忍这个行为。
* 把单精度浮点值换成整型数值,猜猜你的显卡能不能忍这个行为。
* 试试把第六行 comment 掉,不给函数赋任何像素的值。
* 试试把第六行注释掉,不给函数赋任何像素的值。
* 尝试另外写个函数,返回某个颜色,然后把 ```main()``` 放到这个函数里面。给个提示,这个函数应该长这样:

@ -0,0 +1,82 @@
## Hello World
Généralement le "Hello World" est la première étape dans l'apprentissage d'un nouveau langage.
C'est un programme court qui renvoie un message enthousiaste et fait miroiter un avenir radieux.
Au pays du GPU, rendre du texte est une tâche extrêmement complexe (et un champ de recherche très actif NDT) donc au lieu d'un message texte, nous allons choisir une couleur chatoyante pour déchaîner notre enthousiasme!
<div class="codeAndCanvas" data="hello_world.frag"></div>
Si vous lisez ceci dans un navigateur récent, le bloc précédent est interactif.
Cela signifie que vous pouvez cliquer et éditer le code. Les changements seront pris en compte immédiatement, recompilés et si le shader est valide, il sera remplacé *à la volée*.
Vous pouvez essayer de changer les chiffres de la ligne 6.
Si ce program paraît simple, nous pouvons déjà faire quelques observations intéressantes:
1. ça ressemble à du C, un shader possède une fonction ```main``` dont le seul but est d'assigner une couleur.
2. la couleur du pixel est assignée à une variable globale (réservée) ```gl_FragColor```.
3. ce langage aux allures de C, possède des *variables* (comme ```gl_FragColor```), des *fonctions* et des *types*.
dans l'exemple, nous venons de voir le type ```vec4``` qui représente un vecteur de chiffres (des floats) à 4 dimensions. plus tard nous verrons d'autres types comme: ```vec3``` & ```vec2``` et d'autres plus fréquents comme: ```float```, ```int``` & ```bool```.
4. si l'on regarde ```vec4``` de plus près, on peut déduire que les 4 arguments correspondent aux 4 canaux: RED, GREEN, BLUE & ALPHA du pixel.
On note également que les valeurs sont *normalisées*, ce qui signifie qu'elles vont de ```0.0``` à ```1.0```.
plus tard nous verrons pourquoi c'est intéressant de manipuler des valeurs normalisées et comment *mapper* des valeurs entre elles.
5. une autre remarque importante est la présence de *macros de pré-traitement*
les macros font partie de l'étape de précompilation, elles permettent de définir (```#define```) des variables globales et de faire des opérations conditionnelles de base ( avec ```#ifdef``` & ```#endif```).
toutes les macros commencent par un hashtag (```#```).
la précompilation se produit - comme son nom l'indique - avant la compilation du shader, elle copie et renseigne tous les ```#define``` et vérifie si les ```#ifdef``` sont définis et si les ```#ifndef``` ne sont pas définis.
dans l'exemple ci-dessus, ligne 1, nous vérifions uniquement si ```GL_ES``` est défini, ce qui se produit principalement lorsque le code est compilé sur mobile ou dans un navigateur.
6. le type Float est vital dans les shaders, donc le niveau de *précision* des Float est crucial.
une précision basse permet un rendu plus rapide mais une qualité moindre et inversement, une précision élevée permet un meilleur rendu au prix de performances réduites.
on peut spécifier la précision de chaque variable se servant des Float, ligne 2 (```precision mediump float;```), nous assignons la précision *medium* à tous les floats de l'application.
nous pourrions leur donner une valeur *low* (```precision lowp float;```) ou *high* (```precision highp float;```).
7. la dernière remarque, probablement la plus importante, est que les spécifications GLSL ne garantissent pas que les variables seront *castées* automatiquement.
qu'est-ce que cela veut dire? si les fabricants ont des approches différentes pour accélérer leurs cartes graphiques, ils doivent toutefois se conformer à un ensemble de spécifications communes pour être utilisable par le plus grand nombre.
le casting automatique des variables ne fait pas partie des spécifications.
Dans notre exemple, ```vec4``` attend des ```floats``` et rien d'autre. si vous voulez obtenir un code homogène et éviter de passer des heures à débugger un écran blanc, prenez l'habitude de mettre des points ( ```.``` ) dans vos floats.
ce genre de code ne marchera pas toujours:
```glsl
void main() {
gl_FragColor = vec4(1,0,0,1); // ERROR
}
```
alors que celui ci à de plus grandes chances de marcher:
```glsl
void main() {
gl_FragColor = vec4( 1., .0, 0., 1. ); // BETTER
}
```
notez que le point peut être placé avant ou après un *0*.
Maintentant que nous avons passé en revue quelques éléments importants du programme "hello world!", il est temps de clicker sur le bloc de code et de mettre en application ce que nous venons d'apprendre.
Vous remarquerez que le programme ne se recompilera pas tant qu'il restera des erreurs. voici quelques idées intéressantes à tester:
* essayez de remplacer les *float* par des *int* la carte graphique vous autorisera ou non à le faire.
* essayez de commenter ( ```//``` ) la ligne 6 ce qui n'assignera aucune valeur au pixel.
* essayez de créer une fonction qui retourne une couleur en dehors de ```main()``` et essayez de l'utiliser pour assigner la valeur de ```gl_FragColor``` dans ```main()```.
pour vous aider, voici le code d'une fonction qui retourne une ```vec4``` de couleur rouge:
```glsl
vec4 red(){
return vec4(1.0,0.0,0.0,1.0);
}
```
* on peut construire un ```vec4``` de plusieurs façons, essayez de découvrir d'autres manières'. par exemple:
```glsl
vec4 color = vec4(vec3(1.0,0.0,1.0),1.0);
```
Bien que cet exemple ne soit pas très excitant, c'est le plus basique qui soit ; nous donnons à l'ensemble des pixels de l'image la même couleur.
Dans le chapitre suivant, nous verrons comment changer cette couleur en fonction de 2 facteurs: l'espace (l'emplacement du pixel à l'écran) et le temps (le nombre de secondes écoulées depuis le chargement de la page).

@ -0,0 +1,54 @@
## Ciao Mondo
Di solito l'esempio "Ciao Mondo!" è il primo passo per imparare un nuovo linguaggio. Si tratta di un semplice programma di una riga che visualizza un messaggio entusiastico di benvenuto.
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. Gli Shaders hanno una unica funzione ```main``` che alla fine restituisce un colore. Questa caratteristica è molto simile al linguaggio C.
2. Il colore finale dei pixel viene assegnato a una variabile globale riservata ```gl_FragColor```.
3. Questo linguaggio è simile al C e ha *variabili* built-in (come ```gl_FragColor```), *funzioni* e *tipi*. In questo esempio abbiamo introdotto ```vec4``` che è un vettore a virgola mobile(float) di quattro dimensioni. Più avanti incontreremo altri tipi come ```vec3``` e ```vec2``` insieme ai più popolari: ```float```, ```int``` e ```bool```.
4. Se analizziamo il tipo ```vec4``` possiamo dedurre che i quattro argomenti corrispondono ai canali ROSSO, VERDE, BLU e ALFA. Inoltre possiamo notare che questi valori sono *normalizzati*, il che significa che vanno da ```0.0``` a ```1.0```. In seguito, impareremo che normalizzare i valori rendere più facile *mapparli* fra le variabili.
5. Un'altra importante *caratteristica del C* che si può vedere in questo esempio è la presenza di macro del preprocessore. Le macro sono parte di una fase di pre-compilazione. Con loro è possibile ```#define``` variabili globali e fare alcune funzioni condizionali di base (con ```#ifdef``` e ```#endif```). Tutti i comandi macro iniziano con un hashtag (```#```). La pre-compilazione avviene appena prima di compilare lo shader e copia tutte le chiamate a ```#defines``` e verifica ```#ifdef``` (è definito) e ```#ifndef``` (non è definito) nel caso di chiamate condizionali . Nel nostro esempio precedente "Ciao mondo!", abbiamo inserito solo la linea 2 per verificare se ```GL_ES``` è definito, chiamata che avviene soprattutto quando il codice viene compilato su dispositivi mobili e browser.
6. I tipi float sono vitali negli shader, dove il livello di *precisione* è fondamentale. Precisione inferiore significa resa più veloce, ma a scapito della qualità. Si può essere pignoli e specificare la precisione di ogni variabile che utilizza la virgola mobile. Nella prima riga (```precision mediump float;```) stiamo definendo tutti i float a media precisione. Ma possiamo impostare la loro precisione a un livello basso (```precision lowp float;```) o alto (```precision highp float;```).
7. L'ultimo, e forse più importante, dettaglio è che le specifiche GLSL non garantiscono che le variabili siano convertite automaticamente. Cosa significa? I produttori delle carte grafiche hanno differenti approcci per accelerare i processi delle carte grafiche, ma sono costretti a garantire delle specifiche minime. La conversione automatica non è una di queste. Nel nostro esempio "Ciao mondo", ```vec4``` ha precisione in virgola mobile e per questo ci si aspetta dei ```floats```. Se si vuole realizzare un codice omogeneo e non passare ore a fare il debug di schermi bianchi, abituatevi a mettere il punto ( ```.``` ) all'interno dei vostri float. Questo tipo di codice non funziona sempre:
```glsl
void main() {
gl_FragColor = vec4(1,0,0,1); // ERRORE
}
```
Ora che abbiamo descritto gli elementi più rilevanti del nostro programma "ciao mondo!", è il momento di cliccare sul blocco di codice e iniziare a mettere alla prova tutto quello che abbiamo imparato. Noterete che in caso di errore, il programma non sarà in grado di compilare e mostrerà uno schermo bianco. Ci sono alcune cose interessanti da provare, per esempio:
* Provate a sostituire i float con degli integer, la vostra scheda grafica potrebbe o non accettare questo comportamento.
* Commentate la linea 6 e non assegnate alcun valore ai pixel della funzione.
* Provate a fare una funzione separata che restituisce un colore specifico e utilizzarla all'interno del ```main()```. Piccolo suggerimento, ecco il codice per una funzione che restituisce un colore rosso:
```glsl
vec4 red(){
return vec4(1.0,0.0,0.0,1.0);
}
```
* Ci sono diversi modi per costruire dei tipi ```vec4```, prova a scoprire gli altri modi. Per esempio:
```glsl
vec4 color = vec4(vec3(1.0,0.0,1.0),1.0);
```
Anche se questo esempio non è molto eccitante, è il più elementare possibile - stiamo cambiando tutti i pixel all'interno del canvas con il medesimo colore. Nel prossimo capitolo vedremo come cambiare i colori dei pixel utilizzando due tipi di input: spazio (cioè la posizione dei pixel sullo schermo) e il tempo (cioè il numero di secondi da quando la pagina è stata caricata).

@ -0,0 +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!

@ -0,0 +1 @@
## Hello World

@ -38,13 +38,13 @@ GLSL 还有更多惊喜。GPU 的硬件加速支持我们使用角度,三角
## gl_FragCoord
就像 GLSL 有个默认输出值 ```vec4 gl_FragColor``` 一样,它也有一个默认输入值( ```vec4 gl_FragCoord``` )。``` gl_FragCoord```存储了活动线程正在处理的**像素**或**屏幕片**的坐标。有了它我们就知道了屏幕上的哪一个线程正在运转。为什么我们不叫 ``` gl_FragCoord``` uniform (统一值)呢?因为每个像素的坐标都不同,所以我们把它叫做**varying**(变化值)。
就像 GLSL 有个默认输出值 ```vec4 gl_FragColor``` 一样,它也有一个默认输入值( ```vec4 gl_FragCoord``` )。``` gl_FragCoord```存储了活动线程正在处理的**像素**或**屏幕片**的坐标。有了它我们就知道了屏幕上的哪一个线程正在运转。为什么我们不叫 ``` gl_FragCoord``` uniform (统一值)呢?因为每个像素的坐标都不同,所以我们把它叫做 **varying**(变化值)。
<div class="codeAndCanvas" data="space.frag"></div>
上述代码中我们用 ```gl_FragCoord.xy``` 除以 ```u_resolution```,对坐标进行了**规范化**。这样做是为了使所有的值落在 ```0.0``` 到 ```1.0``` 之间,这样就可以轻松把 X 或 Y 的值映射到红色或者绿色通道。
在 shader 的领域我们没有太多要 debug 的,更多地是试着给变量赋一些很炫的颜色,试图做出一些效果。有时你会觉得用 GLSL 编程就像是把一搜船放到了瓶子里。它同地困难、美丽而令人满足。
在 shader 的领域我们没有太多要 debug 的,更多地是试着给变量赋一些很炫的颜色,试图做出一些效果。有时你会觉得用 GLSL 编程就像是把一搜船放到了瓶子里。它同地困难、美丽而令人满足。
![](08.png)
@ -58,4 +58,4 @@ GLSL 还有更多惊喜。GPU 的硬件加速支持我们使用角度,三角
* 你可以用 ```u_time``` 和 ```u_mouse``` 来改变颜色的图案吗?不妨琢磨一些有趣的途径。
经过这些小练习后,你可能会好奇还能用 shader 大法做什么。接下来的章节你会知道如何把你的 shader 和 three.jsProcessing和 openFrameworks 结合起来。
经过这些小练习后,你可能会好奇还能用强大的 shader 做什么。接下来的章节你会知道如何把你的 shader 和 three.jsProcessing和 openFrameworks 结合起来。

@ -0,0 +1,95 @@
## Uniforms
Jusqu'à présent, nous avons vu comment le GPU gère un ensemble de threads parallèles dont le but est d'assigner la couleur d'une partie de l'image finale.
Bien que chaque thread soit *aveugle*, nous devons être capables de passer certaines valeurs depuis le CPU vers le GPU et les threads en question.
Du fait de l'architecture des cartes graphiques, ces valeurs vont devoir être également ( ou *uniform*-ément ) distribuées sur tous les threads et - comme décrit au chapitre 1 - utilisées en *lecture seule*.
Autrement dit, _tous les threads reçoivent les mêmes données, chacun peut les lire mais pas les modifier_.
Ces données s'appellent des ```uniform``` et peuvent prendre les types suivants: ```float```, ```vec2```, ```vec3```, ```vec4```, ```mat2```, ```mat3```, ```mat4```, ```sampler2D``` & ```samplerCube```.
Les uniforms se définissent généralement en haut du shader, juste après avoir défini la précision des floats (et autres macros de prétraitement ).
```glsl
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution; // taille du Canvas (x:largeur en pixels, y:hauteur en pixels)
uniform vec2 u_mouse; // position de la souris (x,y) sur le canvas en pixels
uniform float u_time; // temps écoulé depuis le lancement du shader
```
On peut se représenter les uniforms comme de petits ponts à sens unique allant du CPU (notre programme principal) au GPU (là où sera exécuté le shader).
Les noms peuvent varier selon les implémentations et les plateformes mais dans les exemples suivants, nous utiliserons toujours: ```u_time``` (le temps écoulé depuis le lancement du shader),
```u_resolution``` (la taille du canvas sur lequel le shader est exécuté) & ```u_mouse``` (la position de la souris à l'intérieur du canvas).
Le fait de préfixer les noms des uniforms par ```u_``` est une convention de nommage assez répandue, ça permet de reconnaître facilement le type de cette varibale mais ce n'est pas une obligation.
Par exemple [ShaderToy.com](https://www.shadertoy.com/) utilise les mêmes uniforms avec les noms suivants:
```glsl
uniform vec3 iResolution; // taille du canvas (en pixels)
uniform vec4 iMouse; // position de la souris. xy: courant, zw: au click
uniform float iGlobalTime; // temps écoulé depuis le lancement du shader (en secondes)
```
Notez qu'ils utilisent un ```i``` au lieu de notre ```u_```.
Assez parlé, voyons ce que les uiforms peuvent faire.
dans l'exemple suivant, nous utilisons l'uniform la valeurs absolue ( ```abs( valeur )```) d'une fonction de sinus (```sin( valeur )```) qui prend ```u_time``` - le temps écoulé depuis le lancement du shader - comme argument pour animer la quantité de rouge que nous dessinons sur le canvas.
la fonction de sinus attend un angle comme argument, en utilisant le temps (valeur qui ne cesse de croître), on obtient une valeur qui va osciller infiniment entre ```-1.``` et ```1.```.
la valeur *absolue* d'une fonction de sinus sera quant à elle toujours comprise entre ```0.``` et ```1.``` donc notre valeur de rouge oscillera entre ```0.``` et ```1.```.
<div class="codeAndCanvas" data="time.frag"></div>
On peut constater que ça va vite (par rapport au même traitement sur le CPU), cela vient de l'*accélération matérielle*.
En effet, au chapitre 1 nous avons vu que les GPU implémentent parfois l'accélération *matérielle* de certaines opérations, certaines fonctions trigonométriques telles que:
[```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) & [```clamp()```](../glossary/?search=clamp),
sont donc exécutées _matériellement_ et peuvent aller très (très) vite.
Essayons de jouer avec le code ci dessus.
* Ralentissez la fréquence jusqu'à ce que le changement de couleur deviennent imperceptible.
* Accélérez la fréquence jusqu'à voir une couleur unique sans clignotement.
* donnez des fréquences différentes aux trois canaux (RGB) pour obtenir des motifs et des comportements intéressants.
## gl_FragCoord
De la même manière que la fonction main() du shader expose la variable de sortie: ```vec4 gl_FragColor```, elle nous donne accès à une variable d'entrée ```vec4 gl_FragCoord```
qui contient les coordonnées à l'écran du *pixel*.
ce *pixel* s'appelle en fait un *screen fragment*, qui donne son nom au *fragment shader*.
le *screen fragment* ou plus simplement *fragment* est le _pixel en train d'être traité par le thread_.
la variable ```vec4 gl_FragCoord```, nous donne donc accès à l'emplacement _physique_ (à l'écran) du pixel sur lequel le thread est en train de travailler.
cette variable n'est pas une *uniform* puisqu'elle ne conserve pas la même valeur d'un thread à l'autre, chaque pixel ayant par définition des coordonnées uniques.
la variable ```gl_FragCoord``` s'appelle *varying* puisqu'elle va *varier* d'un thread sur l'autre, c'est la seconde _famille_ de variables qu'on peut utiliser dans un shader.
cette variable est déclarée *implicitement* dans les _vertex-shader_ et passée systématiquement à notre *fragment-shader*, autrement dit, elle est toujours là mais inutile de la chercher dans le code ci dessous.
deuxième chose importante, ```gl_FragColor```, ```gl_FragCoord``` et tous les noms de fonctions ( ```sin()```, ```abs()```, etc. ) sont des noms réservés ; on ne peut pas s'en servir pour créer nos variables.
<div class="codeAndCanvas" data="space.frag"></div>
Dans le code ci-dessus, nous *normalisons* les coordonnées du *fragment* en les divisant par la taille du canvas.
En *normalisant* les coordonnées, elles vont se retrouver comprises entre ```0.0``` & ```1.0``` ce qui permet de *mapper* facilement les valeurs X et Y du *fragment* vers les canaux rouges et verts (R&G) de la couleur de sortie (```gl_FragColor```).
Au pays des shaders, nous avons peu de moyen de débugger une application à part assigner des valeurs criardes aux fragments et essayer de comprendre ce qui se passe.
Vous découvrirez que parfois, coder un shader c'est comme de fabriquer un tout petit bateau dans une bouteille, c'est dur, c'est beau et c'est gratifiant.
![](08.png)
Voyons ce que nous avez appris et compris du code.
* pouvez dire où se trouvent les coordonnées XY ```(0.0,0.0)``` sur notre canvas?
* à votre avis où se trouvent les coordonnées```(1.0,0.0)```, ```(0.0,1.0)```, ```(0.5,0.5)``` et ```(1.0,1.0)```?
* pouvez vous déduire comment utiliser l'uniform ```u_mouse``` sachant que ses valeurs sont passées au shader en _pixels_ et ne sont pas normalisées?
* pouvez vous utiliser ```u_mouse``` pour changer les couleurs?
* pouvez vous inventer une manière intéressante de combiner ```u_time``` et ```u_mouse``` pour créer un motif?
Après ces petits exercices, vous vous demandez sans doute où exercer vos nouveaux talents.
Au chapitre suivant, nous verrons comment fabriquer nos propres outils dans THREE.js, Processing et OpenFrameworks.

@ -0,0 +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.

@ -2,7 +2,7 @@
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 graphic 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 call ```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.
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.
```glsl
#ifdef GL_ES

@ -0,0 +1,7 @@
Learn how to use Uniform variables. Uniform variables, or simply *uniforms* are the variables that carry information equally accessible from all of the threads of your shader. The [GSLS editor](http://editor.thebookofshaders.com/) has three uniforms set up for you.
```glsl
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
```

@ -0,0 +1 @@
## Uniforms

@ -50,3 +50,18 @@ void main() {
gl_FragColor = vec4(st.x, st.y, 0.0, 1.0);
}
### Nicolas
* >You can picture the uniforms like little bridges between the CPU and the GPU
a 'one-way'' bridges that is :) I translated it to:
>We can picture the uniforms as small one-way bridges from the CPU (our main program) to the GPU (where the shader will be executed).
* >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.
I developped a bit more to disambiguate pixel & fragment, I think it's an important step, the first time we meet the word fragment _for real_
* 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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

@ -2,7 +2,7 @@
现在你可能跃跃欲试,想在你熟悉的平台上小试牛刀了。接下来会有一些比较流行的平台的示例代码,展示如何在这些平台上配置 shader。在这个 [github 仓库](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04) 中有本章的三种平台的示例代码)
**注释 1**:如果你不想用这些平台来运行 shader且你想在浏览器外使用 shader你可以下载[glslViewer](https://github.com/patriciogonzalezvivo/glslViewer)。这个 MacOS +树莓派程序直接在终端运行,并且是为本书的例子量身打造的。
**注释 1**:如果你不想用这些平台来运行 shader且你想在浏览器外使用 shader你可以下载[glslViewer](https://github.com/patriciogonzalezvivo/glslViewer)。这个 MacOS+树莓派程序直接在终端运行,并且是为本书的例子量身打造的。
**注释2**:如果你想用 WebGL 显示 shader并不关心其他平台你可以用[glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas) 。这个 web 工具本来是为本书设计的,但是太好用了,所以我常常用在其他项目中。
@ -153,4 +153,4 @@ void ofApp::draw(){
}
```
关于 shader 在 openFrameworks 的更多信息请参考这篇[excellent tutorial](http://openframeworks.cc/tutorials/graphics/shaders.html),作者是 [Joshua Noble](http://thefactoryfactory.com/)。
关于 shader 在 openFrameworks 的更多信息请参考这篇[excellent tutorial](http://openframeworks.cc/ofBook/chapters/shaders.html),作者是 [Joshua Noble](http://thefactoryfactory.com/)。

@ -2,7 +2,7 @@
En este punto seguro estás entusiasmado con poder probar shaders en las plataformas en las que te sientes cómodo. En los siguientes ejemplos veremos como agregarlos el algunos frameworks populares con las mismas uniforms con las que estamos trabajando en este libro. (En el [repositorio de GitHub de este capítulo](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04) encontrarás el código completo de estos ejemplos.)
**Nota 1**: En caso de que no quieras utilizar los shaders en los siguientes frameworks pero quieras hacerlo fuera del navegador, puedes descargar y compilar [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer). Este programa corre en MacOS y en RaspberryPI, permite ejecutar directamente los ejemplos desde la terminal.
**Nota 1**: En caso de que no quieras utilizar los shaders en los siguientes frameworks pero quieras hacerlo fuera del navegador, puedes descargar y compilar [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer). Este programa corre en MacOS y en Raspberry Pi, permite ejecutar directamente los ejemplos desde la terminal.
**Nota 2**: Si no quieres usar WebGl con tus shaders y no te interesan los frameworks siguientes, puedes usar [glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas). Esta herramienta fue diseñada para este libro, pero se volvió tan útil que he terminado usándola en muchos proyectos.
@ -156,4 +156,4 @@ void ofApp::draw(){
}
```
Para mas información sobre shaders en openFrameworks ve a este [excelente tutorial](http://openframeworks.cc/tutorials/graphics/shaders.html) creado por [Joshua Noble](http://thefactoryfactory.com/).
Para mas información sobre shaders en openFrameworks ve a este [excelente tutorial](http://openframeworks.cc/ofBook/chapters/shaders.html) creado por [Joshua Noble](http://thefactoryfactory.com/).

@ -0,0 +1,220 @@
## exécuter vos shaders
Pour les besoins de ce livre comme pour ma pratique artistique, j'ai créé un écosystème d'outils permettant de créer, d'afficher, de partager et d'organiser mes shaders.
Ces outils fonctionnent de la même manière sur Linux Desktop, MacOS, [Raspberry Pi](https://www.raspberrypi.org/) et dans les navigateurs sans avoir besoin d'altérer le code.
**Affichage**: tous les exemples de ce livre sont affichés dans la page grâce à [glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas) qui facilite grandement la fabrication et l'affichage de shaders autonomes.
```html
<canvas class="glslCanvas" data-fragment-url=“yourShader.frag" data-textures=“yourInputImage.png” width="500" height="500"></canvas>
```
Comme vous pouvez le voir, il suffit de créer un élément ```canvas``` auquel on applique la classe ```class="glslCanvas"``` et de lui passer l'url du fragment shader dans ```data-fragment-url```.
Pour en savoir plus, [vous pouvez lire ceci](https://github.com/patriciogonzalezvivo/glslCanvas).
Si vous êtes comme moi, vous aurez sans doute envie de lancer vos shaders en lignes de commandes, dans ce cas vous devriez regarder [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer).
Cette application permet d'incorporer un shader dans un script ```bash``` ou un pipeline Unix et de l'utiliser comme [ImageMagick](http://www.imagemagick.org/script/index.php).
[glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) est aussi un bon moyen de compiler vos shaders sur un [Raspberry Pi](https://www.raspberrypi.org/) et c'est la raison pour laquelle [openFrame.io](http://openframe.io/) l'utilise pour afficher les oeuvres.
Pour en savoir plus, [cliquez ici](https://github.com/patriciogonzalezvivo/glslViewer).
```bash
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutputImage.png
```
**Création**:
Pour améliorer l'expérience de programmation des shaders, j'ai créé un éditeur disponible ici [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor).
L'éditeur est embarqué dans les exemples de ce livre, il met à disposition une série de petits widgets qui rendent l'édition du code GLSL plus tangible et moins abstraite.
Vous pouvez également le lancer dans une fenêtre de navigateur à cette adresse [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/).
Pour en savoir plus, [cliquez ici](https://github.com/patriciogonzalezvivo/glslEditor).
![](glslEditor-01.gif)
Si vous préférez travailler avec [SublimeText](https://www.sublimetext.com/) vous pouvez installer le [package pour glslViewer](https://packagecontrol.io/packages/glslViewer).
Pour en savoir plus, [cliquez ici](https://github.com/patriciogonzalezvivo/sublime-glslViewer).
![](glslViewer.gif)
**Partager**:
l'éditeur en ligne([editor.thebookofshaders.com/](http://editor.thebookofshaders.com/)) vous permet de partager vos shaders!
La version autonome comme la version en ligne de l'éditeur permettent de sauver votre shader en ligne et d'obtenir une url unique.
Il est également possible d'exporter le shader pour qu'il fonctionne sur [openFrame.io](http://openframe.io/).
![](glslEditor-00.gif)
**Organiser**:
Pouvoir partager ses shaders est une bonne chose, en plus de l'export vers [openFrame.io](http://openframe.io/)
j'ai fait un outil permettant d'organiser vos shaders dans une galerie et d'intégrer cette galerie dans n'importe quel site.
il s'appelle [glslGallery](https://github.com/patriciogonzalezvivo/glslGallery), pour en savoir plus, [cliquez ici](https://github.com/patriciogonzalezvivo/glslGallery).
![](glslGallery.gif)
## Lancer vos shaders depuis votre plateforme favorite
Si vous avez déjà programmé à l'aide de frameworks/APIS comme: [Processing](https://processing.org/), [Three.js](http://threejs.org/) ou [OpenFrameworks](http://openframeworks.cc/),
vous êtes sans doute impatients de tester vos shaders dans ces environnements.
Les exemples suivants montrent comment intégrer les shaders sur ces plateformes en conservant les conventions de nommage que nous utiliserons dans ce livre.
Vous retrouverez le code source complet sur le [repo GitHub de ce chapitre](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04).
### Dans **THREE.js**
L'humble et brilliant Ricardo Cabello (alias [MrDoob](https://twitter.com/mrdoob)) a développé avec d'autres [contributeurs](https://github.com/mrdoob/three.js/graphs/contributors), l'un des frameworks WebGL les plus utilisés: [Three.js](http://threejs.org/).
Il existe de nombreuses ressources pour apprendre à se servir de ce framework JavaScript.
L'exemple ci-dessous, vous donne le code nécessaire pour utiliser un shader dans THREE.js.
Notez bien la balise de script appelée ```id="fragmentShader"```, c'est là qu'il faudra coller le code que vous trouverez dans ce livre.
```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>
```
### Dans **Processing**
Initié par [Ben Fry](http://benfry.com/) et [Casey Reas](http://reas.com/) en 2001, [Processing](https://processing.org/) est un framework Java
extraordinairement simple et très puissant qui vous aidera à faire vos premiers pas dans le code créatif (ça a été mon cas).
[Andres Colubri](https://codeanticode.wordpress.com/) a contribué des mises à jour importantes concernant OpenGL et la gestion vidéo dans Processing.
Ces ajouts simplifient énormément l'intégration des shaders GLSL dans l'environnement de développement.
Processing va chercher le shader appelé ```"shader.frag"``` dans le dossier ```data``` du sketch.
Assurez vous de copier les exemples du livre dans ce dossier et de les renommer correctement.
```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);
}
```
Pour que le shader fonctionne dans les versions antérieures à Processing 2.1, il faut ajouter la ligne suivante: ```#define PROCESSING_COLOR_SHADER``` au début du shader.
il devrait ressembler à ça:
```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);
}
```
Pour en savoir plus sur les shaders dans Processing, vous pouvez vous reporter à ce [tutoriel](https://processing.org/tutorials/pshader/).
### Dans **openFrameworks**
Chacun a sa zone de confort, pour moi, ça reste [la communité openFrameworks](http://openframeworks.cc/).
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());
ofRect(0,0,ofGetWidth(), ofGetHeight());
shader.end();
}
```
Pour plus d'informations sur les shader OpenFrameworks, vous pouvez vous reporter à cet [excellent tutoriel](http://openframeworks.cc/ofBook/chapters/shaders.html) écrit par [Joshua Noble](http://thefactoryfactory.com/).

@ -0,0 +1,190 @@
## Eseguite il vostro shader
Nell'ambito della realizzazione di questo libro e della mia pratica artistica ho creato un ecosistema di strumenti per creare, visualizzare, condividere e curare gli shaders. Questo strumento funziona in modo coerente su Linux Desktop, MacOS, [Raspberry Pi](https://www.raspberrypi.org/) e browser, senza la necessità di dover cambiare il vostro codice.
**Visualizzare**: tutti gli esempi di questo libro vengono visualizzati utilizzando [glslCanvas](https://github.com/patriciogonzalezvivo/glslCanvas) che rende il processo di esecuzione dello shader standalone incredibilmente facile.
```html
<canvas class="glslCanvas" data-fragment-url=“yourShader.frag" data-textures=“yourInputImage.png” width="500" height="500"></canvas>
```
Come potete vedere, è solo necessario l'elemento ```canvas``` con l'attributo ```class="glslCanvas"``` e l'indirizzo verso il vostro shader nel ```data-fragment-url```. Scoprite di più a proposito [cliccando qui](https://github.com/patriciogonzalezvivo/glslCanvas).
Se siete come me, probabilmente vorrete eseguire gli shader direttamente dalla console. In questo caso date un'occhiata a [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer). Questa applicazione consente d'incorporare gli shader nel vostro script ```bash``` o pipelines UNIX e d?utilizzarli in modo simile a [ImageMagick](http://www.imagemagick.org/script/index.php). Anche [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) è un ottimo modo per compilare gli shader sul [Raspberry Pi](https://www.raspberrypi.org/), motivo per il quale [openFrame.io](http://openframe.io/) lo usa per visualizzare le opere d'arte di tipo shader. Potete trovare ulteriori informazioni su questa applicazione [cliccando qui](https://github.com/patriciogonzalezvivo/glslViewer).
```bash
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutputImage.png
```
**Creare**: per migliorare la programmazione degli shader, ho realizzato un editor online chiamato [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor). Questo editor è integrato agli esempi del libro e mette a disposizione una serie di comodi widget per rendere più tangibile il codice astratto GLSL. È anche possibile eseguirlo come un'applicazione standalone web da [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/). Scoprite di più a proposito [cliccando qui](https://github.com/patriciogonzalezvivo/glslEditor).
![](glslEditor-01.gif)
Se si preferisce lavorare offline utilizzando [SublimeText](https://www.sublimetext.com/) è possibile installare questo [pacchetto per glslViewer](https://packagecontrol.io/packages/glslViewer). Scoprite di più [cliccando qui](https://github.com/patriciogonzalezvivo/sublime-glslViewer).
![](glslViewer.gif)
**Condividere**: l'editor online ([editor.thebookofshaders.com/](http://editor.thebookofshaders.com/)) può condividere i tuoi shader! Sia la versione standalone che quella integrata hanno un pulsante per esportare con il quale è possibile ottenere un URL unico verso il vostro shader. Avete anche la possibilità d'esportare direttamente verso un [openFrame.io](http://openframe.io/).
![](glslEditor-00.gif)
**Curare**: Condividere il vostro codice è la prima tappa per intendere il vostro shader come un'opera d'arte! Accanto alla possibilità di esportare verso [openFrame.io](http://openframe.io/) ho fatto uno strumento per curare i vostri shader in una galleria che può essere integrata su qualsiasi sito, il suo nome è [glslGallery](https://github.com/patriciogonzalezvivo/glslGallery). Per saperne di più [cliccando qui](https://github.com/patriciogonzalezvivo/glslGallery).
![](glslGallery.gif)
## Eseguire i vostri shader nel vostro framework preferito
Nel caso in cui si dispone già di esperienze di programmazione in framework quali: [Processing](https://processing.org/), [Three.js](http://threejs.org/) o [OpenFrameworks](http://openframeworks.cc/), probabilmente sarete ansiosi di provare gli shader sulle piattaforme su cui vi trovate bene. I seguenti sono esempi di come impostare gli shader in alcuni dei framework più popolari con le stesse uniforms che andremo ad utilizzare in questo libro. (Nella [repository GitHub per questo capitolo](https://github.com/patriciogonzalezvivo/thebookofshaders/tree/master/04), troverete il codice sorgente completo per questi tre framework.)
### In **Three.js**
Il brillante e molto umile Ricardo Cabello (aka [MrDoob](https://twitter.com/mrdoob)) ha sviluppato insieme ad altri [collaboratori](https://github.com/mrdoob/three.js/graphs/contributors), probabilmente uno dei più famosi framework per WebGL, chiamato [Three.js](http://threejs.org/). Troverete un sacco di esempi, tutorial e libri che vi insegneranno come utilizzare questa libreria JavaScript per fare grafica 3D.
Di seguito è riportato un esempio di codice HTML e JS per iniziare con gli shader in three.js. Prestate attenzione allo script ```id="fragmentShader"```, qui è dove è possibile copiare gli shader che si trovano in questo libro.
```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**
Iniziato da [Ben Fry](http://benfry.com/) e [Casey Reas](http://reas.com/) nel 2001, [Processing](https://processing.org/) è un framework straordinariamente semplice e potente in cui muovere i primi passi nel codice (o almeno lo è stato per me). [Andres Colubri](https://codeanticode.wordpress.com/) ha fatto importanti aggiornamenti a openGL e la gestione video in Processing, rendendo più facile che mai usare e giocare con i GLSL shader. Processing cercherà lo shader chiamato ```"shader.frag"``` nella cartella ```data``` dello sketch. Assicuratevi di copiare gli esempi che trovate qui in quella cartella e rinominate il file.
```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);
}
```
Affinché lo shader lavori su versioni precedenti alla 2.1, è necessario aggiungere la seguente riga all'inizio del vostro Shader: ```#define PROCESSING_COLOR_SHADER```. In questo modo dovrebbe assomigliare a:
```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);
}
```
Per ulteriori informazioni sugli shader in Processing controllate questo [tutorial](https://processing.org/tutorials/pshader/).
### 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());
ofRect(0,0,ofGetWidth(), ofGetHeight());
shader.end();
}
```
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/).

@ -183,4 +183,4 @@ void ofApp::draw(){
}
```
openFrameworksでシェーダーを使う方法についてより詳しく知りたい場合は[Joshua Noble](https://processing.org/tutorials/pshader/)の[素晴らしいチュートリアル](http://openframeworks.cc/tutorials/graphics/shaders.html) を参照してください。
openFrameworksでシェーダーを使う方法についてより詳しく知りたい場合は[Joshua Noble](http://openframeworks.cc/ofBook/chapters/shaders.html)の[素晴らしいチュートリアル](http://openframeworks.cc/tutorials/graphics/shaders.html) を参照してください。

@ -150,4 +150,4 @@ void ofApp::draw(){
}
```
더 자세한 정보는 [Joshua Noble](http://thefactoryfactory.com/)가 만든 [강좌](http://openframeworks.cc/tutorials/graphics/shaders.html)를 보기 바란다.
더 자세한 정보는 [Joshua Noble](http://thefactoryfactory.com/)가 만든 [강좌](http://openframeworks.cc/ofBook/chapters/shaders.html)를 보기 바란다.

@ -1,22 +1,22 @@
## Running your shader
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, [RaspberryPi](https://www.raspberrypi.org/) and browsers without the need of changing your code.
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 life-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>
```
As you can see, it just need to a ```canvas``` element with ```class="glslCanvas"``` and the url to your shader in the ```data-fragment-url```. Learn more about it [here](https://github.com/patriciogonzalezvivo/glslCanvas).
As you can see, it just needs a ```canvas``` element with ```class="glslCanvas"``` and the url to your shader in the ```data-fragment-url```. Learn more about it [here](https://github.com/patriciogonzalezvivo/glslCanvas).
If you are like me, you will probably want to run shaders directly from the console, in that case you should check out [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer). This application allows you to incorporate shaders into your ```bash``` scripts or unix pipelines and use it in a similarly in a similar way that [ImageMagic](http://www.imagemagick.org/script/index.php). Also [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) is a great way to compile shaders on your [RaspberryPi](https://www.raspberrypi.org/), reason why [openFrame.io](http://openframe.io/) use it to display shader artwork. Learn more about this application [here](https://github.com/patriciogonzalezvivo/glslViewer).
If you are like me, you will probably want to run shaders directly from the console, in that case you should check out [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer). This application allows you to incorporate shaders into your ```bash``` scripts or unix pipelines and use it in a similar way that [ImageMagick](http://www.imagemagick.org/script/index.php). Also [glslViewer](https://github.com/patriciogonzalezvivo/glslViewer) is a great way to compile shaders on your [Raspberry Pi](https://www.raspberrypi.org/), reason why [openFrame.io](http://openframe.io/) use it to display shader artwork. Learn more about this application [here](https://github.com/patriciogonzalezvivo/glslViewer).
```bash
glslViewer yourShader.frag yourInputImage.png —w 500 -h 500 -s 1 -o yourOutputImage.png
```
**Create**: in order to illuminate the experience of coding shaders I made an online editor call [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor). This editor is embebed on the book's life examples, it brings a series of handy widgets to make more tangible the abstract experience of working with glsl code. You can also run it as a standalone web application from [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/). Learn more about it [here](https://github.com/patriciogonzalezvivo/glslEditor).
**Create**: in order to illuminate the experience of coding shaders I made an online editor called [glslEditor](https://github.com/patriciogonzalezvivo/glslEditor). This editor is embedded on the book's live examples, it brings a series of handy widgets to make more tangible the abstract experience of working with glsl code. You can also run it as a standalone web application from [editor.thebookofshaders.com/](http://editor.thebookofshaders.com/). Learn more about it [here](https://github.com/patriciogonzalezvivo/glslEditor).
![](glslEditor-01.gif)
@ -24,7 +24,7 @@ If you prefer to work offline using [SublimeText](https://www.sublimetext.com/)
![](glslViewer.gif)
**Share**: the online editor ([editor.thebookofshaders.com/](http://editor.thebookofshaders.com/)) can share your shaders! Both the embebed and standalone version have an export button where you can get an unique URL's to your shader. Also have the ability to export directly to an [openFrame.io](http://openframe.io/).
**Share**: the online editor ([editor.thebookofshaders.com/](http://editor.thebookofshaders.com/)) can share your shaders! Both the embedded and standalone version have an export button where you can get an unique URL's to your shader. Also have the ability to export directly to an [openFrame.io](http://openframe.io/).
![](glslEditor-00.gif)
@ -187,4 +187,4 @@ void ofApp::draw(){
}
```
For more information about shaders in openFrameworks go to this [excellent tutorial](http://openframeworks.cc/tutorials/graphics/shaders.html) made by [Joshua Noble](http://thefactoryfactory.com/).
For more information about shaders in openFrameworks go to this [excellent tutorial](http://openframeworks.cc/ofBook/chapters/shaders.html) made by [Joshua Noble](http://thefactoryfactory.com/).

@ -0,0 +1 @@
## Running your shader

@ -13,7 +13,7 @@
这些代码就是你的基本功;遵守和理解它非常重要。你将会一遍又一遍地回到 0.0 到 1.0 这个区间。你将会掌握融合与构建这些代码的艺术。
这些 x 与 y或亮度之间一对一的关系称作**线性插值**linear interpolation译者注插值是离散函数逼近的重要方法利用它可通过函数在有限个点处的取值状况估算出函数在其他点处的近似值。因为对机器运算来说,屏幕像素注定是离散的而不是连续的,计算机图形学常用插值来填充图像变换时像素之间的空隙。)现在起我们可以用一些数学函数来改造这些代码行。比如说我们可以做一个求 x 的 5 次幂的曲线。
这些 x 与 y或亮度之间一对一的关系称作**线性插值**linear interpolation译者注插值是离散函数逼近的重要方法利用它可通过函数在有限个点处的取值状况估算出函数在其他点处的近似值。因为对计算机来说,屏幕像素是离散的而不是连续的,计算机图形学常用插值来填充图像像素之间的空隙。)现在起我们可以用一些数学函数来改造这些代码行。比如说我们可以做一个求 x 的 5 次幂的曲线。
<div class="codeAndCanvas" data="expo.frag"></div>
@ -107,11 +107,11 @@ GLSL 还有一些独特的原生插值函数可以被硬件加速。
[Iñigo Quiles](http://www.iquilezles.org/) 收集了一套[有用的函数](http://www.iquilezles.org/www/articles/functions/functions.htm)。在看过[这篇文章](http://www.iquilezles.org/www/articles/functions/functions.htm)后,看看下列函数转换到 GLSL 的样子。注意那些细小的改变比如给浮点数float)加小数点“.”给“C 系函数”换成它们在 GLSL 里的名字,比如不是用 ```powf()``` 而是用 ```pow()```
* [Impulse](../edit.html#05/impulse.frag)
* [Cubic Pulse](../edit.html#05/cubicpulse.frag)
* [Exponential Step](../edit.html#05/expstep.frag)
* [Parabola](../edit.html#05/parabola.frag)
* [Power Curve](../edit.html#05/pcurve.frag)
* [Impulse](../edit.php#05/impulse.frag)
* [Cubic Pulse](../edit.php#05/cubicpulse.frag)
* [Exponential Step](../edit.php#05/expstep.frag)
* [Parabola](../edit.php#05/parabola.frag)
* [Power Curve](../edit.php#05/pcurve.frag)
给你们看些东西刺激一下斗志,这里有一个非常优雅的例子(作者是 [Danguafer](https://www.shadertoy.com/user/Danguafer),造型函数的空手道黑带)。

@ -108,11 +108,11 @@ Como los chefs que colectan especias e ingredientes exóticos, los artistas digi
[Iñigo Quiles](http://www.iquilezles.org/) tiene una gran colección de [funciones útiles](http://www.iquilezles.org/www/articles/functions/functions.htm). Después de leer [este artículo](http://www.iquilezles.org/www/articles/functions/functions.htm) echa un vistazo a la traducción de esas funciones a GLSL. Presta atención a los pequeños cambios necesarios, como poner "." (punto) en los valores flotantes y usar los nombres en GLSL de las *funciones en C*; por ejemplo en vez de ```powf()``` usamos ```pow()```:
* [Impulse](../edit.html#05/impulse.frag)
* [Cubic Pulse](../edit.html#05/cubicpulse.frag)
* [Exponential Step](../edit.html#05/expstep.frag)
* [Parabola](../edit.html#05/parabola.frag)
* [Power Curve](../edit.html#05/pcurve.frag)
* [Impulse](../edit.php#05/impulse.frag)
* [Cubic Pulse](../edit.php#05/cubicpulse.frag)
* [Exponential Step](../edit.php#05/expstep.frag)
* [Parabola](../edit.php#05/parabola.frag)
* [Power Curve](../edit.php#05/pcurve.frag)
Para que te mantengas motivado, aqui hay un elegante ejemplo (hecho por [Danguafer](https://www.shadertoy.com/user/Danguafer)) de alguien que logró dominar su karate en las funciones.

@ -0,0 +1,189 @@
# Dessin Algorithmique
## fonctions de formes
Ce chapitre aurait pu s'appeler "la palissade de monsieur Miyagi" (ndt [pour ceux qui n'étaient pas nés en 1984](https://fr.wikipedia.org/wiki/Karat%C3%A9_Kid_(film,_1984))).
Au chapitre précédent, nous avons *mappé* les coordonnées *x* et *y* *normalisées* sur les canaux *rouge* et *vert*.
Nous avons créé une *fonction* qui prend un vecteur à deux dimensions (x et y) et retourne un vecteur à quatre dimensions (r, g, b et a).
Avant de transformer des données à plusieurs dimensions, il nous faut commencer par des choses simples... beaucoup plus simples.
Concrètement, nous devons comprendre commment marchent les fonctions à une dimension.
Plus vous passerez de temps à apprendre et à maîtriser ces fonctions, plus votre Karaté-Shader sera redoutable.
![The Karate Kid (1984)](mr_miyagi.jpg)
Le code suivant sera notre palissade.
Sur cette palissade, nous visualisons la valeur normalisée de la position *x* (```st.x```) de deux façons: la luminosité (c'est le joli dégradé du noir au blanc en arrière plan) et une ligne verte dessinée par dessus (dans ce cas, la valeur *x* est assignée directement à *y*).
Ne vous focalisez pas trop sur la fonction ```plot``` pour l'instant, nous y reviendrons en détail dans un moment.
<div class="codeAndCanvas" data="linear.frag"></div>
**Note**: Le constructeur du type ```vec3```, un vecteur à 3 dimensions (r,g,b ou x,y,z ; c'est la même chose), "comprend" que vous allez le construire avec la même valeur pour les trois canaux/dimensions.
il est donc possible d'ecrire ```vec3 color = vec3( y );``` pour construire un vecteur à 3 dimensions. Ce vecteur aura la valeur ```y``` assignée à chaque canal/dimension soit: ```color.x = color.y = color.z = y``` ou ```color.r = color.g = color.b = y``` (puisqu'on peut accéder aux variables du vecteur des 2 manières).
Le constructeur du type ```vec4``` en revanche, "comprend" que vous allez le construire, soit en passant quatre valeurs dinstinctes: ```vec4( 0.,0.5,1.,1.)```, soit en lui passant un ```vec3``` et un ```float``` (un nombre) : ```vec4( color, 1.)```.
Dans notre cas, la valeur du second paramètre (le ```float```), permet de gérer l'*opacité* aussi appelé l'*alpha*.
Référez vous aux lignes 20 et 26 dans l'exemple ci-dessus pour bien voir la différence de construction des 2 types.
Ce code sera votre palissade ; il est important de bien l'observer et de bien le comprendre.
Vous reviendrez souvent dans cet espace entre *0.0* and *1.0* pour maîtriser l'art de le transformer et de sculpter cette ligne.
La relation entre *x* et *y* ( la luminosité du dégradé ), s'appelle une *interpolation*.
Comme on passe une seule valeur (*y*) à la variable *color*, on obtient un niveau de gris et comme la valeur de *x* est *normalisée*, elle est comprise entre *0.0* et *1.0*, on obtient un dégradé du noir (*x=0.*) au blanc (*x=1.*).
L'*interpolation* est un principe fondamental ; elle nous permet de faire passer progressivement une valeur de *A* vers *B* en fonction d'une troisième valeur *T* normalisée entre *0.0* et *1.0*.
La ligne verte reflète ce qui se passe lors de l'interpolation, en l'occurrence, c'est une ligne droite puisque *x* passe de *0.0* à *1.0* de façon linéaire (*x* va de *0.0* à *1.0* de façon continue).
A partir de là, nous pouvons utiliser des fonctions mathématiques pour *sculpter* la ligne. Par exemple, on peut passer *x* à la puissance 5 pour créer une ligne *courbe*.
<div class="codeAndCanvas" data="expo.frag"></div>
Intéressant n'est-ce-pas? A la ligne 19, au lieu de ```5.0``` essayez différents exposants, par exemple: 20.0, 2.0, 1.0, 0.0, 0.2 et 0.02.
Comprendre la relation qui existe entre la valeur et l'exposant va nous être très utile.
Ce genre de fonction mathématique nous donne un contrôle sur l'*expressivité* du code, c'est une sorte d'acupuncture qui permet de contrôle les flux de valeurs.
[```pow()```](../glossary/?search=pow) est une fonction native de GLSL et il y en a de nombreuses autres.
La plupart sont accélérées matériellement, ce qui signifie que si on les utilise bien et avec parcimonie, elle permettent au code de s'exécuter plus vite.
Essayez de remplacer la fonction ```pow()``` ligne 19 par: [```exp()```](../glossary/?search=exp), [```log()```](../glossary/?search=log) ou [```sqrt()```](../glossary/?search=sqrt).
Certaines de ces fonctions deviennent vraiment intéressantes quand on les utilise avec PI. Vous pouvez voir que j'ai déclaré une macro qui remplacera chaque appel à ```PI``` par la valeur ```3.14159265359```.
par exemple: ```sin( st.x * PI )```, produira une parabole, ```pow( sin( st.x * PI ), 5. )``` effectuera un *pincement* de la parabole.
### Step et Smoothstep
GLSL propose également des fonctions d'interpolation natives et accélrées matériellement.
La fonction [```step()```](../glossary/?search=step) prend 2 paramètres, le premier est une *limite* ou un *seuil* et le second est la valeur à tester.
Toute valeur inférieure au *seuil* renverra ```0.0``` tandis que toute valeur supérieure au *seuil* renverra ```1.0```.
essayez de changer la valeur de *seuil* à la ligne 20 du code suivant.
<div class="codeAndCanvas" data="step.frag"></div>
L'autre fonction d'interpolation s'appelle [```smoothstep()```](../glossary/?search=smoothstep).
Avec deux nombres *A* et *B* et une valeur d'interpolation *T* comprise entre *0.0* et *1.0*, elle nous permet de passer de progressivement (et en souplesse) de *A* à *B* en fonction de *T*.
les deux premiers arguments sont les *bornes* ( *A* et *B* ) et le troisième est la valeur d'interpolation (*T*).
<div class="codeAndCanvas" data="smoothstep.frag"></div>
Dans l'exemple ci-dessus, ligne 12, vous remarquez qu'on a utilisé ```smoothstep()``` depuis le début dans la fonction ```plot()``` qui permet de dessiner la ligne verte.
Pour chaque position le long de l'axe des *x*, cette fonction crée une *bosse* à un endroit précis de l'axe des *y*.
Comment? en combinant deux appels à [```smoothstep()```](../glossary/?search=smoothstep).
Remplacez la ligne 20 par la fonction suivante et regardez l'arrière plan, on dirait une ligne floutée non?
En rapprochant les valeurs de *seuil* des ```smoothstep()``` ( *0.45,0.5* et *0.5,0.55* par exemple), la ligne devient plus fine et moins floue.
```glsl
float y = smoothstep(0.2,0.5,st.x) - smoothstep(0.5,0.8,st.x);
```
### Sinus et Cosinus
Le mieux, si vous voulez utiliser les maths pour animer ou passer d'une valeur à une autre, c'est d'être copain avec les sinus/cosinus.
Ces deux fonctions trigonométriques combinées permettent de dessiner des cercles qui sont plus utiles que le couteau suisse de MacGyver.
Il est important de comprendre ce qu'elles font et comment les combiner.
Dans un mouchoir de poche, à partir d'un angle en radians (1 radian = PI / 180), le [cosinus](../glossary/?search=cos) renvoie la position *x* et le [sinus](../glossary/?search=sin) renvoie la position *y* d'un point sur un cercle de rayon 1.
Le fait que ces fonctions renvoient des valeurs *normalisées* (entre -1 et 1) de manière très 'continue' ou très 'souple', en fait un outil indispensable.
![](sincos.gif)
S'il est difficile de comprendre cette relation entre sinus/cosinus et le cercle unitaire (de rayon 1), l'animation ci-dessus la résume assez bien visuellement.
<div class="simpleFunction" data="y = sin(x);"></div>
Regardez attentivement cette sinusoïde et surtout comment la valeur *y* oscille entre -1 et 1.
Comme nous l'avons vu sur l'exemple du temps au chapitre 3, on peut utiliser cette propriété temporelle de [```sin()```](../glossary/?search=sin) pour animer une valeur.
Si vous regardez cet exemple dans un navigateur, vous pouvez changer le code de la forumle ci-dessus pour voir comment la sinusoïde change (n'oubliez pas le point-virule en fin de ligne).
Essayez les changements suivants et regardez ce qui se passe:
* ajoutez le temps (```u_time```) à *x* avant de calculer ```sin```. Retenez ce **mouvement** le long des *x*.
* Multipliez *x* par ```PI``` avant de calculer ```sin```. remarquez comme les deux *phases* **rétrécissent** de manière à ce que chaque cycle (tour complet) se répète entre deux valeurs entières.
* Multipliez le temps (```u_time```) par *x* avant de calculer ```sin```. remarquez comme la **fréquence** entre phases se compresse. Notez qu'u_time peut déjà avoir une valeur très élevée, rendant le graphe illisible.
* Ajoutez 1.0 à [```sin(x)```](../glossary/?search=sin). Notez que toutes les vagues se **déplacent** vers le haut et comme toutes les valeurs sont maintenant comprises entre 0 et 2.
* Multipliez [```sin(x)```](../glossary/?search=sin) par 2.0 et notez comme l'**amplitude** doubles de taille.
* calculez la valeur absolue ([```abs()```](../glossary/?search=abs)) de ```sin(x)```, on dirait que le tracé **rebondit**.
* Utilisez la partie fractionnelle (uniquement les chiffres après la virgule) ([```fract()```](../glossary/?search=fract)) du résultat de [```sin(x)```](../glossary/?search=sin).
* Ajoutez l'entier le plus grand ([```ceil()```](../glossary/?search=ceil)) à l'entier le plus petit ([```floor()```](../glossary/?search=floor)) du résultat de [```sin(x)```](../glossary/?search=sin) pour obtenir des *créneaux* entre -1 et 1.
### quelques fonctions indispensables
A la fin de l'exercice précédent, nous avons présenté quelques nouvelles fonctions, nous allons maintenant les tester.
Pour ce faire, décommentez une ligne à la fois dans la liste suivante.
Essayez de comprendre comment chacune fonctionne et comment vous pourriez les combiner.
Vous vous demandez sans doute mais... pourquoi?
Une petite recherche de "generative art" sur Google vous apportera la réponse.
Gardez à l'esprit que ces fonctions sont votre palissade, nous apprenons à maîtriser le mouvement sur une dimension, de bas en haut, puis de haut en bas.
Bientôt, nous utiliserons, deux, trois et même quatre dimensions!
![Anthony Mattox (2009)](anthony-mattox-ribbon.jpg)
<div class="simpleFunction" data="y = mod(x,0.5); // renvoie x modulo 0.5
//y = fract(x); // renvoie uniquement la partie fractionnelle d'un chiffre (les chiffres après la virgule)
//y = ceil(x); // renvoie le plus proche entier supérieur ou égal à x
//y = floor(x); // renvoie le plus proche entier inférieur ou égal à x
//y = sign(x); // renvoie le signe de x (-1 ou 1)
//y = abs(x); // renvoie la valeur absolue de x
//y = clamp(x,0.0,1.0); // force x à se retrouver entre 0.0 et 1.0
//y = min(0.0,x); // renvoie le plus petit chiffre entre 0 et x
//y = max(0.0,x); // renvoie le plus grand chiffre entre 0 et x"></div>
### fonctions de formes avancées
[Golan Levin](http://www.flong.com/) a écrit quelques articles très instructifs sur des fonctions plus complexes.
Les porter en GLSL est une bonne idée si vous souhaitez construire votre boîte à outils.
* [fonctions Polynomiales: www.flong.com/texts/code/shapers_poly](http://www.flong.com/texts/code/shapers_poly/)
* [fonctions Exponentielles: www.flong.com/texts/code/shapers_exp](http://www.flong.com/texts/code/shapers_exp/)
* [fonctions Circulaires & Elliptiques: www.flong.com/texts/code/shapers_circ](http://www.flong.com/texts/code/shapers_circ/)
* [fonctions de Bezier et autres fonctions paramétriques: www.flong.com/texts/code/shapers_bez](http://www.flong.com/texts/code/shapers_bez/)
Comme un chef qui collectionnerait les épices et autres ingrédients exotiques, les artistes digitaux et les codeurs créatifs en particulier aiment travailler leurs propres fonctions de forme.
[Iñigo Quiles](http://www.iquilezles.org/) a écrit une liste de [fonctions utiles](http://www.iquilezles.org/www/articles/functions/functions.htm).
Après avoir lu [cet article](http://www.iquilezles.org/www/articles/functions/functions.htm) regardez leur traduction en GLSL.
Notez bien les petits changements nécessaires, comme le "." (point) sur les floats et l'utilisation des conventions de nommage GLSL pour les fonctions C ; par exemple ```powf()``` devient ```pow()```:
* [Impulse](../edit.php#05/impulse.frag)
* [Cubic Pulse](../edit.php#05/cubicpulse.frag)
* [Exponential Step](../edit.php#05/expstep.frag)
* [Parabola](../edit.php#05/parabola.frag)
* [Power Curve](../edit.php#05/pcurve.frag)
Pour vous motiver, voici un exemple élégant, fait par [Danguafer](https://www.shadertoy.com/user/Danguafer) qui montre le karaté des fonctions de formes.
<iframe width="800" height="450" frameborder="0" src="https://www.shadertoy.com/embed/XsXXDn?gui=true&t=10&paused=true" allowfullscreen></iframe>
au prochain chapitre, nous utiliserons ces nouveaux mouvements. D'abord pour mélanger des couleurs, puis pour dessiner des formes.
#### Exercices
Regardez cette table d'équations, réalisée par [Kynd](http://www.kynd.info/log/).
Voyez comme il combine les fonctions et leurs propriétés pour contrôler les variations de valuer entre 0 et 1.
A présent, c'est à votre tour de vous entraîner à reproduire ces fonctions.
Souvenez vous que plus vous pratiquerez, meilleur sera votre karaté.
![Kynd - www.flickr.com/photos/kynd/9546075099/ (2013)](kynd.png)
#### Pour la boîte à outils
Voici quelques outils qui simplifient la visualisation des fonctions.
* Grapher: si vous avez un MAC, tapez ```grapher``` dans spotlight et vous pourrez utiliser cet outil très pratique.
![OS X Grapher (2004)](grapher.png)
* [GraphToy](http://www.iquilezles.org/apps/graphtoy/): [Iñigo Quilez](http://www.iquilezles.org), encore lui, a créé un outil pour visualiser les fonctions GLSL en WebGL.
![Iñigo Quilez - GraphToy (2010)](graphtoy.png)
* [Shadershop](http://tobyschachman.com/Shadershop/): [Toby Schachman](http://tobyschachman.com/) a créé cet outil génial qui permet de construire des fonctions de façon très intuitive.
![Toby Schachman - Shadershop (2014)](shadershop.png)

@ -0,0 +1,141 @@
# Disegno Algoritmico
## Funzioni di forma
Questo capitolo potrebbe essere chiamato "la lezione del recinto di Mr. Miyagi". In precedenza abbiamo associato la posizione normalizzata di *x* e *y* ai canali *rosso* e *verde*. Fondamentalmente abbiamo creato una funzione che prende un vettore bidimensionale (x e y) e restituisce un vettore quadridimensionale (r, g, b e a). Ma prima di andare avanti nella trasformazione dei dati tra dimensioni, dobbiamo iniziare da qualcosa di più semplice…molto più semplice. Questo significa comprendere come creare funzioni unidimensionali. Maggiori sono lenergia e il tempo che impieghi nel comprendere e nel padroneggiarle, migliore sarà il tuo karate shader.
![The Karate Kid (1984)](mr_miyagi.jpg)
La seguente struttura di codice sarà la nostra recinzione. In questa visualizziamo il valore normalizzato della coordinata *x* (```st.x```) in due modi: uno con la luminosità (osserva il bel gradiente dal nero al bianco) e laltro tracciando sopra una linea verde (in questo caso il valore di *x* è assegnato direttamente al valore di *y*). Non ti concentrare troppo sulla funzione plot, la vedremo nel dettaglio tra poco.
<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.
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.
Questa relazione uno a uno tra *x* e *y* (o la luminosità) è conosciuta come *interpolazione lineare*. A partire da qui, possiamo usare alcune funzioni matematiche per *modellare* la linea. Per esempio, possiamo elevare *x* alla quinta potenza e creare una linea *curva*.
<div class="codeAndCanvas" data="expo.frag"></div>
Interessante, vero? Alla riga 22 prova esponenti diversi, per esempio: 20.0, 2.0, 1.0, 0.0, 0.2 e 0.02. comprendere questa relazione tra il valore e lesponente sarà molto utile. Questo genere di funzioni matematiche ci darà un controllo espressivo sul codice, come una specie di agopuntura che permette di controllare il flusso dei valori.
[```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.
Linterpolazione [```step()```](../glossary/?search=step) riceve due parametri. Il primo è il limite o la soglia, mentre il secondo è il valore che volgiamo controllare. Qualsiasi valore al di sotto del limite tornerà a ```0.0```, mentre tutto ciò al di sopra del limite tornerà a ```1.0```.
Prova a cambiare il valore della soglia alla riga 20 del seguente codice.
<div class="codeAndCanvas" data="step.frag"></div>
Laltra funzione unica è conosciuta come [```smoothstep()```](../glossary/?search=smoothstep). Data una serie di due numeri e un valore, questa funzione interpolerà il valore tra la serie definita. I primi due parametri sono per linizio e la fine della transizione, mentre il terzo è per il valore dinterpolazione.
<div class="codeAndCanvas" data="smoothstep.frag"></div>
Nellesempio precedente, alla riga 12, nota che abbiamo usato smoothstep ( ) per disegnare la linea verde sulla funzione ```plot()```. Per ciascuna posizione lungo lasse *x*, questa funzione crea un *salto* ad un particolare valore di *y*. Come? Collegando tra di loro due [```smoothstep()```](../glossary/?search=smoothstep). Guarda la funzione qui di seguito, sostituiscila alla riga 20 di sopra e pensa ad esso come ad un taglio verticale. Lo sfondo assomiglia ad una linea, vero?
```glsl
float y = smoothstep(0.2,0.5,st.x) - smoothstep(0.5,0.8,st.x);
```
### Seno e coseno.
Quando si vuole usare la matematica per animare, modellare o combinare, non cè nulla di meglio che essere amici del seno e del coseno.
Queste due basiche funzioni trigonometriche lavorano congiuntamente per costruire cerchi che sono utili come il coltellino svizzero di MacGyver. È importante sapere come si comportano e in che modo possono essere combinate. In breve: dato un angolo (in radianti), essi ritorneranno alla corretta posizione di *x* ([cosine](../glossary/?search=cos)) e di *y* ([sine](../glossary/?search=sin)) di un punto sul margine del cerchio con raggio uguale a 1. Il fatto che queste funzioni ritornano ai valori normalizzati ( tra -1 e 1) in modo così armonioso e fluido le rende uno strumento incredibile.
![](sincos.gif)
Mentre è difficile descrivere tutte le relazioni tra le funzioni trigonometriche e i cerchi, le animazioni soprastanti le riassumono molto bene visivamente.
<div class="simpleFunction" data="y = sin(x);"></div>
Guarda attentamente questa curva sinusoidale. Nota come i valori di *y* ondeggiano dolcemente tra +1 e -1. Come abbiamo visto nellesempio del tempo nel capitolo precedente, si può usare questo comportamento ritmico di [```sin()```](../glossary/?search=sin) per animare le proprietà. Se stai leggendo questo esempio su un browser, vedrai che puoi cambiare il codice nella formula soprastante per osservare come cambia londa. (Nota: non dimenticare il punto e virgola alla fine delle righe).
Prova questi esercizi e osserva cosa succede:
* Aggiungi tempo (```u_time```) a *x* prima di calcolare ```sin```. Osserva attentamente questo **movimento** lungo *x*.
* Moltiplica *x* per ```PI``` prima di calcolare ```sin```. Nota come le due fasi si **restringano** e ciascun ciclo si ripeta tra due valori interi.
* Moltiplica tempo (```u_time```) per *x* prima di calcolare ```sin```. Osserva come la **frequenza** tra le fasi diventi sempre più compressa. Nota che u_time può avere già assunto un valore molto grande, rendendo il grafico difficile da leggere.
* Aggiungi 1.0 a [```sin(x)```](../glossary/?search=sin). Osserva come tutte le onde siano **dislocate** verso lalto e adesso tutti i valori siano tra 0.0 e 2.0.
* Moltiplica [```sin(x)```](../glossary/?search=sin) per 2.0. Osserva come l**ampiezza** raddoppi di misura.
* Calcola il valore assoluto ([```abs()```](../glossary/?search=abs)) di ```sin(x)```. Sembra la traccia di una palla che **rimbalza**.
* Estrai solo la parte frazionaria ([```fract()```](../glossary/?search=fract)) della risultante di [```sin(x)```](../glossary/?search=sin).
* Aggiungi il numero intero più elevato ([```ceil()```](../glossary/?search=ceil)) e il più basso ([```floor()```](../glossary/?search=floor)) della risultante di [```sin(x)```](../glossary/?search=sin) per ottenere unonda digitale dei valori 1 e -1.
### Altre funzioni utili
AAl termine dellultimo esercizio abbiamo presentato alcune nuove funzioni. È arrivato il momento di provare con ciascuna, decommentando le righe sottostanti, una alla volta. Impara quete funzioni e studia il loro comportamento. Lo so, ti stai chiedendo perché e se cerchi velocemente su Google "arte generativa" capirai subito. Ricorda che queste funzioni sono il nostro recinto. Stiamo controllando il movimento in una dimensione, su e giù. Presto arriverà il momento per due, tre e quattro dimensioni!
![Anthony Mattox (2009)](anthony-mattox-ribbon.jpg)
<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 = 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
//y = min(0.0,x); // restituisce il valore più piccolo fra x e 0.0
//y = max(0.0,x); // restituisce il valore più grande fra x e 0.0"></div>
### 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.
* [Polynomial Shaping Functions: www.flong.com/texts/code/shapers_poly](http://www.flong.com/texts/code/shapers_poly/)
* [Exponential Shaping Functions: www.flong.com/texts/code/shapers_exp](http://www.flong.com/texts/code/shapers_exp/)
* [Circular & Elliptical Shaping Functions: www.flong.com/texts/code/shapers_circ](http://www.flong.com/texts/code/shapers_circ/)
* [Bezier and Other Parametric Shaping Functions: 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>
Come i cuochi collezionano con passione spezie e ingredienti esotici, così gli artisti digitali e i creative coders adorano lavorare sulle proprie funzioni di forma.
[Iñigo Quiles](http://www.iquilezles.org/) possiede una grande raccolta di [funzioni molto utili](http://www.iquilezles.org/www/articles/functions/functions.htm). Dopo aver letto [quest'articolo](http://www.iquilezles.org/www/articles/functions/functions.htm), leggi le seguenti traduzioni di queste funzioni in GLSL. Fai attenzione ai piccoli cambiamenti necessari, come mettere "."" (punto) sui valori flessibili, e usare il nome GLSL per le *funzioni in C*; per esempio, invece di ```powf()```, usa ```pow()```:
<div class="glslGallery" data="05/impulse,05/cubicpulse,05/expo,05/expstep,05/parabola,05/pcurve" data-properties="clickRun:editor,hoverPreview:false"></div>
Per mantenere alta la tua motivazione, qui trovi un esempio elegante dellessere esperti nel karate delle funzioni di forma (creato da [Danguafer](https://www.shadertoy.com/user/Danguafer)).
<iframe width="800" height="450" frameborder="0" src="https://www.shadertoy.com/embed/XsXXDn?gui=true&t=10&paused=true" allowfullscreen></iframe>
Nel *Prossimo >>* capitolo inizieremo ad usare nuove mosse. Prima mescolando i colori e poi disegnando forme.
#### Esercizio
Guarda la seguente tabella di equazioni fatta da [Kynd](http://www.kynd.info/log/). Osserva come combini le funzioni e le loro proprietà per controllare i valori tra 0.0 e 1.0. Ora è il tuo momento di fare pratica replicando queste funzioni. Ricordati: più ti eserciti, migliore sarà il tuo karate.
![Kynd - www.flickr.com/photos/kynd/9546075099/ (2013)](kynd.png)
#### Per la tua cassetta degli attrezzi
Qui trovi alcuni strumenti che ti faciliteranno la visualizzazione di questi tipi di funzione.
* Grapher: se hai un computer MacOS, digita ```grapher``` nel tuo spotlight e riuscirai ad usare questo magnifico attrezzo.
![OS X Grapher (2004)](grapher.png)
* [GraphToy](http://www.iquilezles.org/apps/graphtoy/): ancora una volta [Iñigo Quilez](http://www.iquilezles.org) ha creato un mezzo per visualizzare le funzioni GLSL in WebGL.
![Iñigo Quilez - GraphToy (2010)](graphtoy.png)
* [Shadershop](http://tobyschachman.com/Shadershop/): questo favoloso mezzo creato da [Toby Schachman](http://tobyschachman.com/) ti insegnerà a costruire funzioni complesse in un modo visivo ed incredibilmente intuitivo.
![Toby Schachman - Shadershop (2014)](shadershop.png)

@ -117,11 +117,11 @@ GLSLには他にも、値を変化させるのに使うことができるネイ
[Iñigo Quiles](http://www.iquilezles.org/)は便利な関数の[素晴らしいコレクション](http://www.iquilezles.org/www/articles/functions/functions.htm)を持っています。 [この記事](http://www.iquilezles.org/www/articles/functions/functions.htm)をまず読んでから、下記にあるGLSLへ翻訳したバージョンを見てみましょう。浮動小数点の数値に「.小数点」を追加したり、Cの関数をGLSL特有の関数名で置き換える、例えば ```powf()``` の代わりに ```pow()``` を使うなどの細かな変更点に注意してください。
* [Impulse](../edit.html#05/impulse.frag)
* [Cubic Pulse](../edit.html#05/cubicpulse.frag)
* [Exponential Step](../edit.html#05/expstep.frag)
* [Parabola](../edit.html#05/parabola.frag)
* [Power Curve](../edit.html#05/pcurve.frag)
* [Impulse](../edit.php#05/impulse.frag)
* [Cubic Pulse](../edit.php#05/cubicpulse.frag)
* [Exponential Step](../edit.php#05/expstep.frag)
* [Parabola](../edit.php#05/parabola.frag)
* [Power Curve](../edit.php#05/pcurve.frag)
匠の技を見てモチベーションを上げましょう。[Danguafer](https://www.shadertoy.com/user/Danguafer)の作品です。

@ -108,11 +108,11 @@ GLSL에는 하드웨어 가속화된 내장 보간법 함수들이 존재한다.
[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.html#05/impulse.frag)
* [Cubic Pulse](../edit.html#05/cubicpulse.frag)
* [Exponential Step](../edit.html#05/expstep.frag)
* [Parabola](../edit.html#05/parabola.frag)
* [Power Curve](../edit.html#05/pcurve.frag)
* [Impulse](../edit.php#05/impulse.frag)
* [Cubic Pulse](../edit.php#05/cubicpulse.frag)
* [Exponential Step](../edit.php#05/expstep.frag)
* [Parabola](../edit.php#05/parabola.frag)
* [Power Curve](../edit.php#05/pcurve.frag)
계속 작업이 뜨겁게 진행되는것을 도울수 있게 여기 멋진 작업도 소개해본다. (made by [Danguafer](https://www.shadertoy.com/user/Danguafer))

@ -17,11 +17,11 @@ This one-to-one relationship between *x* and *y* (or the brightness) is know as
<div class="codeAndCanvas" data="expo.frag"></div>
Interesting, right? On line 19 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.
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.
Replace the power function on line 19. 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 5 that I have defined a macro that will replace any call to ```PI``` with the value ```3.14159265359```.
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
@ -103,15 +103,13 @@ At the end of the last exercise we introduced some new functions. Now its tim
* [Bezier and Other Parametric Shaping Functions: 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>
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()```:
* [Impulse](../edit.html#05/impulse.frag)
* [Cubic Pulse](../edit.html#05/cubicpulse.frag)
* [Exponential Step](../edit.html#05/expstep.frag)
* [Parabola](../edit.html#05/parabola.frag)
* [Power Curve](../edit.html#05/pcurve.frag)
<div class="glslGallery" data="05/impulse,05/cubicpulse,05/expo,05/expstep,05/parabola,05/pcurve" data-properties="clickRun:editor,hoverPreview:false"></div>
To keep your motivation up, here is an elegant example (made by [Danguafer](https://www.shadertoy.com/user/Danguafer)) of mastering the shaping-functions karate.

@ -0,0 +1 @@
Shaping functions is fundamental technique that is recursively used throughout this book that let you control the variation of the value at will. Study how different functions of x are used to create different shapes and try making your own function.

@ -0,0 +1,2 @@
# Algorithmic drawing
## Shaping functions

@ -1,3 +1,6 @@
// Author: Inigo Quiles
// Title: Cubic Pulse
#ifdef GL_ES
precision mediump float;
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

@ -1,3 +1,6 @@
// Author: Inigo Quiles
// Title: Expo
#ifdef GL_ES
precision mediump float;
#endif

@ -1,3 +1,6 @@
// Author: Inigo Quiles
// Title: ExpStep
#ifdef GL_ES
precision mediump float;
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

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

@ -1,3 +1,6 @@
// Author: Inigo Quiles
// Title: Impulse
#ifdef GL_ES
precision mediump float;
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

@ -5,3 +5,6 @@
* What is smoothstep()? This example starts to lose me. There are many new elements here. Could you include a step by step walkthrough of this whole example before proceeding to the next part?
* 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 :)

@ -1,3 +1,6 @@
// Author: Inigo Quiles
// Title: Parabola
#ifdef GL_ES
precision mediump float;
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

@ -1,3 +1,6 @@
// Author: Inigo Quiles
// Title: Pcurve
#ifdef GL_ES
precision mediump float;
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

@ -67,7 +67,7 @@ green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue
试着来 show 一下你所学到的:
* 给颜色赋予一个有趣的过渡。想想某种特定的感情。哪种颜色更具代表性他如何产生又如何褪去再想想另外的一种感情以及对应的颜色。然后改变上诉代码中的代表这种情感的开始颜色和结束颜色。Robert Penner 开发了一些列流行的计算机动画塑形函数,被称为[缓动函数](http://easings.net/)。你可以研究这些[例子](../edit.html#06/easing.frag)并得到启发,但最好你还是自己写一个自己的缓动函数。
* 给颜色赋予一个有趣的过渡。想想某种特定的感情。哪种颜色更具代表性他如何产生又如何褪去再想想另外的一种感情以及对应的颜色。然后改变上诉代码中的代表这种情感的开始颜色和结束颜色。Robert Penner 开发了一些列流行的计算机动画塑形函数,被称为[缓动函数](http://easings.net/)。你可以研究这些[例子](../edit.php#06/easing.frag)并得到启发,但最好你还是自己写一个自己的缓动函数。
### 玩玩渐变

@ -65,7 +65,7 @@ Echa un vistazo al siguiente código en la línea 18 y observa cómo estamos usa
Demuestra tus habilidades:
* Crea una transición expresiva entre dos colores. Piensa en una emoción en particular. ¿Qué color es el más representativo de esa emoción? ¿Cómo aparece? ¿Cómo se desvanece? Piensa en otra emoción y el color que la represente. Cambia los colores del código de arriba por los de tus emociones. Luego anima las transiciones utilizando las funciones de forma. Robert Penner desarrolló una serie de funciones de forma populares, conocidas como [easing functions](http://easings.net/), puedes usar [este ejemplo](../edit.html#06/easing.frag) como investigación o inspiración, pero los mejores resultados saldrán cuando crees tus propias transiciones.
* Crea una transición expresiva entre dos colores. Piensa en una emoción en particular. ¿Qué color es el más representativo de esa emoción? ¿Cómo aparece? ¿Cómo se desvanece? Piensa en otra emoción y el color que la represente. Cambia los colores del código de arriba por los de tus emociones. Luego anima las transiciones utilizando las funciones de forma. Robert Penner desarrolló una serie de funciones de forma populares, conocidas como [easing functions](http://easings.net/), puedes usar [este ejemplo](../edit.php#06/easing.frag) como investigación o inspiración, pero los mejores resultados saldrán cuando crees tus propias transiciones.
### Jugando con gradientes

@ -0,0 +1,268 @@
## Couleurs
![Paul Klee - Charte Couleur (1931)](klee.jpg)
Jusqu'ici, nous avons manipulé des vecteurs mais nous n'avons pas encore pris le temps de voir comment marchent ces variables.
Avant d'aller plus loin, il est important d'en savoir plus sur ces variables.
Aborder la couleur est un bon moyen de se pencher sur la question.
Si vous connaissez la Programmation Orientée Objet, vous aurez remarqué que nous accédons aux données des vecteurs comme on le ferait avec des ```struct``` en C, grâce à des **accesseurs / mutateurs** ( **getters / setters** en anglais).
[NDT]bien que cette pratique soit méconnue, il es possible d'utiliser des ```struct``` en GLSL, [plus d'informations ici](https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance/glsl/misc/shader-with-array-of-structs-uniform.html) [/NDT]
```glsl
vec3 red = vec3(1.0,0.0,0.0);
red.x = 1.0;
red.y = 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```.
Définir une couleur avec *x*, *y* et *z* peut être un peu déroutant, c'est pourquoi il existe différentes manières d'accéder aux valeurs des propriétés des vectuers.
Les valeurs de ```.x```, ```.y``` et ```.z``` peuvent être récupérées avec les **accesseurs** ```.r```, ```.g``` et ```.b```, ou ```.s```, ```.t``` et ```.p```. (```.s```, ```.t``` et ```.p``` sont généralement utilisées pour encoder les coordonnées spatiales des textures, nous verrons ça dans les chapitres suivants).
Il est également possible d'accéder aux valeurs des propriétés des vecteurs par leur position d'index dans l'objet: ```[0]```, ```[1]``` and ```[2]```.
Les lignes suivantes montrent les différentes manières d'accéder aux données:
```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;
```
[NDT]on peut les utiliser ces **accesseurs** de façon indépendante ; le code suivant crée un clone *newColor* du vecteur *color* en utilisant chaque fois un accesseur différent.
```glsl
vec4 color = vec4( 1.,0.,0.5,1. );
vec4 newColor = vec4( color[0], color.g, color.z, color.q );
```
Il est possible de combiner les propriétés en **concaténant** les accesseurs: si on veut exploiter les valeurs ```.r```, ```.g``` et ```.b``` d'un vecteur 4 sans se soucier de ```.a``` (l'alpha), on peut écrire:
```glsl
vec4 color = vec4( 1.,0.,0.5,1. );
vec4 newColor = vec4( color.rgb, 1.0 );
```
Ce qui revient à cloner chaque proriété ```.r```, ```.g``` et ```.b``` du vecteur ```color``` sauf la dernière ```.a```.
Dans ce cas, ```color.rgb``` est interprété comme un vecteur de type ```vec3``` et il contient les valeurs ```.r```, ```.g``` et ```.b``` du ```vec4``` *color*.
De même, si on écrit:
```glsl
vec4 color = vec4( 1.,0.,0.5,1. );
vec3 newColor = vec3( color.xy, 1.0 );
```
On va utiliser les valeurs ```.x``` et ```.y``` de *color* pour construire un ```vec3``` dont les valeurs ```.r``` et ```.g``` seront les mêmes que les valeurs ```.r``` et ```.g``` du vecteur *color* et où la valeur ```.b``` sera ```1.0```.
Dernière chose, l'ordre dans lequel on **concatène** les accesseurs est important.
Si on veut construire un vecteur à partir d'un autre mais en inversant l'ordre des propriétés, on peut l'écrire comme suit:
```glsl
vec3 color = vec3( 1.0, 0.0, 0.5 );
vec3 newColor = color.bgr;
```
le vecteur *newColor* va copier les propriétés de *color* mais au lieu de les copier dans l'ordre "normal":```.r```, ```.g``` et ```.b```,
il va les copier dans l'ordre inverse: ```.b```, ```.g``` et ```.r```.
```glsl
color.r => 1.0
color.g => 0.0
color.b => 0.5
et
newColor.r => 0.5
newColor.g => 0.0
newColor.b => 1.0
```
Il en découle que si les déclarations suivantes sont équivalentes:
```glsl
color.rgba = color.xyzw = color.stpq
```
ces déclarations ne le sont pas:
```glsl
color.rgba != color.argb != color.rbga != color.abgr etc.
color.xyzw != color.wxyz != color.xzyw != color.wzyx etc.
color.stpq != color.qstp != color.sptq != color.qpts etc.
```
C'est une fonctionnalité très puissante ; elle permet de stocker les informations dans un format compact.
Un exemple d'utilisation, si on veut décrire un rectangle, on peut se servir soit de 2 ```vec2``` décrivant respectivement le coin supérieur gauche et le coin inférieur droit,
ou bien, utiliser un seul ```vec4``` dont l'**accesseur** ```.xy``` renverra un ```vec2``` décrivant le coin supérieur gauche, et l'**accesseur** ```.zw``` renverra un ```vec2``` décrivant le coin inférieur droit.
[/NDT]
Ces différentes manière d'accéder aux variables à l'intérieur des vecteurs sont simplement là pour nous aider à écrire un code lisible.
Cette souplesse d'utilisation est le point d'entrée qui vous permettra de penser aux espaces cartésiens (le "vrai" espace) et colorimétriques de façon interchangeable.
La concaténation prend tout son sens lorsqu'on veut pouvoir combiner des vecteurs dans un ordre arbitraire pour les mélanger (cette propriété s'appelle le *swizzle*).
```glsl
vec3 jaune, magenta, vert;
// crée le jaune
jaune.rg = vec2(1.0); // Assigne 1. au canaux rouges et vert du vecteur jaune
jaune[2] = 0.0; // Assigne 0. au canal bleu du vecteur jaune
// crée le magenta
magenta = jaune.rbg; // Assigne the valeur en intervertissant le vert et le bleu ( rbg au lieu de rgb )
// crée le vert
vert.rgb = jaune.bgb; // Assigne le canal bleu du jaune (0) aux canaux rouges et bleus
```
#### Pour la boîte à outils
Si vous êtes incapables de choisir des couleurs par le biais des chiffres, c'est normal ; cela peut être très contre-intuitif.
Heureusement pour nous, il existe de nombreux programmes qui nous simplifient la tâche.
Trouvez celui qui vous convient et apprenez à formater vos couleurs en ```vec3``` ou ```vec4```.
Par exemple, voici les gabarits que j'utilise avec [Spectrum](http://www.eigenlogik.com/spectrum/mac):
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### Mélanger les couleurs
A présent que nous savons définir les couleurs, il est temps de les utiliser avec ce que nous avons déjà appris.
En GLSL, il existe une fonction extrêmement utile [```mix()```](../glossary/?search=mix), qui permet de mélanger deux valeurs en fonction d'un pourcentage.
[NDT]comme vu au chapitre précédent, ```mix()``` permet d'interpoler entre 2 valeurs grâce à une troisième valeur T.
exactement comme ```smoothstep()``` à la différence que cette fois, la fonction ```mix()``` prend en argument des vecteurs au lieu de *floats*.
[/NDT]
Pouvez vous deviner ce que devra être le pourcentage?
Evidemment, une valeur normalisée entre *0.0* et *1.0*!
Ce qui nous va très bien, après tout ce temps passé sur la palissade du chapitre précédent, il est enfin temps de frapper!
![](mix-f.jpg)
Observez la ligne 18: notez que nous utilisons la valeur absolue (```abs()```) d'une fonction de sinus (```sin()```) prenant le temps en argumanet pour contrôler le mélange entre ```colorA``` et ```colorB```.
<div class="codeAndCanvas" data="mix.frag"></div>
Montrez de quoi vous êtes capable
* Créez une transition expressive entre les couleurs. Pensez à une émotion en particulier.
* quelle couleur représente le mieux cette émotion? comment apparaît-elle? comment disparaît-elle?
* pensez à une autre émotion et à la couleur correspondante, changez les couleur A et B dans le code puis utilisez les fonctions de formes pour opérer la transition.
Robert Penner a développé une série de fonctions destinées à créer des animations, connues sous le nom d'[easing functions](http://easings.net/).
Vous pouvez utiliser [cet exemple](../edit.php#06/easing.frag) comme base de recherche mais les meilleures transitions seront celles que vous ferez vous mêmes.
### Jouer avec les dégradés
La fonction [```mix()```](../glossary/?search=mix) peut faire plus.
Au lieu de passer un seul ```float``` pour faire l'interpolation, nous pouvons passer successivement plusieurs valeurs de transition.
Dans l'exemple suivant, nous passons les valeurs ```r```, ```g``` et ```b``` d'un ```vec3``` (```pct``` pour *pourcentage* ) pour contrôler le mélange des canaux.
![](mix-vec.jpg)
Regardez l'exemple suivant.
Comme au chapitre précédent, nous branchons la valeur de transition sur la valeur normalisée de *x* et nous la visualisons par une ligne.
Au début, rien d'exceptionnel, le dégradé est linéaire sur les trois canaux.
A présent, décommentez la ligne 25 et regardez ce qui se passe, puis décommentez les lignes 26 et 27.
Rappelez vous que les lignes représentent la quantité de mélange entre ```colorA``` et ```colorB``` par canal de couleur.
<div class="codeAndCanvas" data="gradient.frag"></div>
Vous aurez sans doute reconnu les 3 fonctions de forme du chapitre précédent aux lignes 25,26,27.
A vous de jouer! Il est temps d'explorer et de créer des dégradés intéressants en ré-utilisant ce que nous avons vu au chapitre précédent.
Essayez les exercices suivants:
![William Turner - The Fighting Temeraire (1838)](turner.jpg)
* Composez un dégradé qui ressemble au coucher de soleil ci-dessus
* Animez une transition entre lever et coucher de soleil en utilisant ```u_time```.
* pouvez vous créer un arc-en-ciel avec ce que vous avez appris jusqu'à présent?
* Utilisez la fonction ```step()``` pour créer un drapeau.
### HSB
On ne peut pas parler de couleur sans parler d'espace colorimétrique. Vous le savez sans doute mais il existe plusieurs façons d'organiser les canaux rouge, vert, bleu.
[HSB](http://en.wikipedia.org/wiki/HSL_and_HSV) signifie "Hue, Saturation, Brightness (ou Value)" soit en bon français "Teinte, Saturation, Luminosité", c'est une manière plus intuitive d'organiser les couleurs.
Prenez un instant pour lire et essayer de comprendre les méthodes ```rgb2hsv()``` et ```hsv2rgb()``` dans le code suivant.
En indexant la Teinte (Hue) sur la position en *x* et la Luminosité (Brigthness) sur la position en *y*, nous obtenons un spectre des couleurs complet.
Cette distribution spatiale des couleurs peut être très pratique ; il est plus simple de choisir une couleur dans un espace HSB que dans un espace RGB.
<div class="codeAndCanvas" data="hsb.frag"></div>
### HSB et coordonnées polaires
A l'origine, HSB a été conçu pour être représenté dans un système de coordonnées polaires.
[NDT]Par opposition à un système de coordonnées cartésien décrit par 2 axes *X* et *Y* orthogonaux, un système de coordonnées polaires, est décrit par des *angles* et des *rayons*.[/NDT]
Pour dessiner notre fonction HSB, nous devons obtenir la position du centre du canvas de manière à connaître l'*angle* et la *distance* de chaque fragment au centre.
Pour cela nous allons utiliser la méthode [```length()```](../glossary/?search=length) et [```atan(y,x)```](../glossary/?search=atan) qui est l'équivalent GLSL de la méthode ```atan2(y,x)```.
Lorsqu'on utilise des vecteurs avec des fonctions trigonométriques les variables de type ```vec2```, ```vec3``` et ```vec4``` sont considérées comme des vecteurs géométriques même si elles représentent des couleurs.
Nous commencerons à traiter les couleurs et les vecteurs géométriques de façon similaire, en fait, vous devriez comprendre assez vite que cette flexibilité d'utilisation est une force.
**Note:** Si vous vous demandez s'il existe d'autres fonctions géométriques que [```length```](../glossary/?search=length)
comme: [```distance()```](../glossary/?search=distance), [```dot()```](../glossary/?search=dot), [```cross```](../glossary/?search=cross), [```normalize()```](../glossary/?search=normalize), [```faceforward()```](../glossary/?search=fraceforward), [```reflect()```](../glossary/?search=reflect) et [```refract()```](../glossary/?search=refract), la réponse est oui.
GLSL expose également des méthodes pour comparer les vecteurs entres eux: [```lessThan()```](../glossary/?search=lessThan), [```lessThanEqual()```](../glossary/?search=lessThanEqual), [```greaterThan()```](../glossary/?search=greaterThan), [```greaterThanEqual()```](../glossary/?search=greaterThanEqual), [```equal()```](../glossary/?search=equal) et [```notEqual()```](../glossary/?search=notEqual).
Une fois que nous avons récupéré l'angle entre le centre et le fragment en cours, nous devons le normaliser.
Ligne 27, [```atan(y,x)```](../glossary/?search=atan) nous retourne un angle en radians compris entre *-PI* et *PI* (~-3.14 to ~3.14), pour le normaliser, nous devons diviser cet angle par *2 x PI*, la macro ```TWO_PI``` en début de code nous permet de stocker cette valeur.
En divisant l'angle par ```TWO_PI```, nous obtenons un chiffre compris entre *-0.5* (```-PI / TWO_PI```) et *0.5* (```PI / TWO_PI```) auquel il nous suffit d'ajouter 0.5 pour qu'il soit compris entre *0.0* et *1.0*.
Le rayon (la distance du centre au fragment) retournera une valeur max de 0.5 en *x* et en *y* (parce que nous calculons la distance depuis le centre du canvas),
nous devons donc doubler cette valeur (en la multipliant par 2) pour obtenir un *rayon* compris entre *0.0* et *1.0*.
Vous voyez que tout est question de ramener les valeurs dans l'espace entre *0.0* et *1.0*, un espace *normalisé*.
<div class="codeAndCanvas" data="hsb-colorwheel.frag"></div>
Essayez les exercices suivants:
* Modifiez l'exemple des coordonnées polaires pour faire tourner les couleurs.
* Utilisez les fonctions de formes avec les fonctions de conversion HSB vers RGB pour étendre une valeur de teinte spécifique et rétrécir le reste.
![William Home Lizars - Red, blue and yellow spectra, with the solar spectrum (1834)](spectrums.jpg)
* si vous regardez attentivement la roue des couleurs qu'utilisent les sélecteurs de couleurs (voir l'image ci-dessous), ils affichent un spectre différent basé sur du RYB.
Par exemple, la couleur opposée au rouge devrait être le vert mais dans nos exemples, c'est le Cyan.
Pouvez vous trouver un moyen d'arranger ça de manière à obtenir exactement le meme rendu que sur l'image? [indice: c'est un bon moment pour vous servir des fonctions de formes.]
![](colorwheel.png)
* Lisez [le livre de Josep's Alvers: l'interaction des couleurs](http://www.goodreads.com/book/show/111113.Interaction_of_Color) et servez vous des exemples suivants pour vous entraîner à reproduire ses exemples.
<div class="glslGallery" data="160505191155,160505193939,160505200330,160507154604,160507160421" data-properties="clickRun:editor,openFrameIcon:false,showAuthor:false"></div>
#### A propos des fonctions et des arguments
Avant de passer au chapitre suivant, attardons nous un peu sur les fonctions du dernier exemple.
Vous remarquerez un ```in``` avant les types des arguments.
C'est ce qu'on appelle un [*qualifier*](http://www.shaderific.com/glsl-qualifiers/#inputqualifier) et dans ce cas précis, cela signifie que la variable est en lecture seule.
Dans les exemples suivants, nous verrons qu'il est également possible de donner les *qualifiers* ```out``` et ```inout``` aux variables passées aux fonctions.
Cette dernière, ```inout```, est équivalente à passer un argument *par référence* en C ; cela nous donne la possibilité de modifier la valeur de la variable passée en argument.
```glsl
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.

@ -0,0 +1,144 @@
![Paul Klee - Color Chart (1931)](klee.jpg)
## Colori
Non abbiamo ancora avuto occasione di parlare dei tipi di vettore in GLSL. Prima di andare avanti, è importante imparare meglio come funzionano queste variabili e parlare di colori è un buon modo per capirle meglio.
Se siete pratici con i paradigmi di programmazione orientata agli oggetti, probabilmente avrete notato che stiamo accedendo ai dati interni ai vettori, come se fossero una qualunque ```struct``` di C.
```glsl
vec3 red = vec3(1.0,0.0,0.0);
red.x = 1.0;
red.y = 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]```.
Le righe seguenti mostrano tutti i modi per accedere agli stessi valori:
```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;
```
Questi diversi modi di indicare le variabili allinterno di un vettore sono solo nomenclature progettate per aiutarvi nella scrittura di un codice chiaro. Tale flessibilità incorporata nel linguaggio shading è una porta per iniziare a pensare allintercambiabilità tra colore e coordinate spaziali.
Unaltra grandiosa caratteristica dei tipi di vettore in GLSL è che le proprietà possono essere combinate in qualsiasi ordine voi vogliate, e ciò rende più facile manipolare e mescolare i valori. Questabilità è chiamata *swizzle*.
```glsl
vec3 yellow, magenta, green;
// Per creare il giallo
yellow.rg = vec2(1.0); // Assegnare 1. ai canali del rosso e del verde
yellow[2] = 0.0; // Assegnare 0. al canale del blu
// Per fare il magenta
magenta = yellow.rbg; // Invertite il canale del verde con quello del blu
// Per ottenere il verde
green.rgb = yellow.bgb; // Assegnare il canale blu del giallo (0) ai canali rosso e blu
```
#### 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):
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### Mescolare i colori
Ora che sapete come sono definiti i colori, è tempo di integrare ciò con le nostre conoscenze precedenti. In GLSL cè una funzione molto utile, [```mix()```](../glossary/?search=mix), che vi permette di mescolare due valori in percentuali. Riuscite ad indovinare lestensione della percentuale? Esatto, i valori tra 0.0 e 1.0! Dopo lunghe ore di esercizio, finalmente è ora di mettere le vostre conoscenze in pratica!
![](mix-f.jpg)
Guardate il codice seguente alla riga 18 e osservate come stiamo usando i valori assoluti di unonda sinusoidale nel tempo per mescolare ```colorA``` e ```colorB```.
<div class="codeAndCanvas" data="mix.frag"></div>
Mettete in risalto le vostre capacità:
* Create una transizione espressiva tra colori. Pensate a unemozione particolare. Quale colore la rappresenta meglio? Come appare? Come si dissolve? Pensate ad unaltra emozione e al colore corrispondente. Cambiate il colore iniziale e finale del codice soprastante per ricreare quelle emozioni. Poi animate la transizione usando le funzioni di forma. Robert Penner ha sviluppato una serie di funzioni di forma famose per animazioni al computer, note come [easing functions](http://easings.net/). Potete usare questesempio come ricerca ed ispirazione ma il risultato migliore sarà ottenuto facendo le vostre transizioni.
### Giocare con i gradienti
La funzione [```mix()```](../glossary/?search=mix) ha molto da offrire. Invece di usare un solo ```float```, possiamo passare un tipo di variabile che abbina i primi due argomenti, nel nostro caso un ```vec3```. Facendo così, possiamo controllare le percentuali di ciascun canale colore ```r```, ```g``` e ```b```.
![](mix-vec.jpg)
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.
<div class="codeAndCanvas" data="gradient.frag"></div>
Probabilmente riconoscerete le tre funzioni di forma che stiamo usando dalla riga 25 alla 27. Giocate con queste! È il momento per esplorare e mostrare le vostre abilità acquisite nel capitolo precedente e creare gradienti interessanti. Provate i seguenti esercizi:
![William Turner - The Fighting Temeraire (1838)](turner.jpg)
* Create un gradiente che assomigli al tramonto di William Turner.
* Animate una transizione tra un'alba e un tramonto usando ```u_time```.
* Riuscite a creare un arcobaleno usando ciò che abbiamo imparato fino ad ora?
* Usate la funzione ```step()``` per creare una bandiera variopinta.
### HSB
Non possiamo parlare di colore senza menzionare lo spazio di colore. Come probabilmente saprete, ci sono diversi modi di organizzare il colore, oltre ai canali del rosso, verde e blu.
[HSB](https://it.wikipedia.org/wiki/Hue_Saturation_Brightness) sta per Hue (Tonalità), Saturation (Saturazione) e Brightness (Luminosità o Valore) ed è un modo di organizzare i colori più intuitivo e utile. Prendete un momento per leggere le funzioni ```rgb2hsv()``` e ```hsv2rgb()``` nel codice seguente.
Mappando la posizione sull'asse x con la tonalità e la posizione sull'asse y con la luminosità, otteniamo uno spettro dei colori visibili. Questa distribuzione spaziale del colore può essere molto pratica; è più intuitivo selezionare un colore con HSB che con RGB.
<div class="codeAndCanvas" data="hsb.frag"></div>
### 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)```).
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.
**Nota:** se ve lo stavate chiedendo, esistono altre funzioni geometriche oltre a [```length```](../glossary/?search=length), come: [```distance()```](../glossary/?search=distance), [```dot()```](../glossary/?search=dot), [```cross```](../glossary/?search=cross), [```normalize()```](../glossary/?search=normalize), [```faceforward()```](../glossary/?search=fraceforward), [```reflect()```](../glossary/?search=reflect) e [```refract()```](../glossary/?search=refract). Anche GLSL ha speciali funzioni vettoriali come: [```lessThan()```](../glossary/?search=lessThan), [```lessThanEqual()```](../glossary/?search=lessThanEqual), [```greaterThan()```](../glossary/?search=greaterThan), [```greaterThanEqual()```](../glossary/?search=greaterThanEqual), [```equal()```](../glossary/?search=equal) e [```notEqual()```](../glossary/?search=notEqual).
Una volta che otteniamo l'angolo e la lunghezza dobbiamo "normalizzare" i loro valori in una scala tra 0.0 e 1.0. alla riga 27, [```atan(y,x)```](../glossary/?search=atan) restituirà un angolo in radianti tra PI e PI (-3.14 e 3.14), quindi dobbiamo dividere questo numero per ```TWO_PI``` (definito nella parte superiore del codice) per ottenere valori tra -0.5 e 0.5, che con una semplice addizione cambiamo nella scala desiderata tra 0.0 e 1.0. Il raggio restituirà un massimo di 0.5 (perché stiamo calcolando la distanza dal centro del punto di osservazione), quindi abbiamo bisogno di raddoppiare questa distanza (moltiplicando per due) per ottenere un massimo di 1.0.
Come potete vedere, il nostro gioco qui riguarda semplicemente il trasformare e manipolare le distanze tra 0.0 e 1.0.
<div class="codeAndCanvas" data="hsb-colorwheel.frag"></div>
Provate gli esercizi successivi:
* Modificate l'esempio polare per ottenere una ruota di colori che gira, proprio come l'icona del mouse che indica il caricamento.
* Usate una funzione di forma unita alla funzione di conversione da HSB a RGB per espandere un particolare valore di tonalità e comprimere il resto.
![William Home Lizars - Red, blue and yellow spectra, with the solar spectrum (1834)](spectrums.jpg)
* Se guardate da vicino la ruota cromatica usata dai selettori del colore (guardate l'immagine qui sotto), essi usano uno spettro diverso da quello dello spazio di colore RYB. Per esempio, il colore opposto al rosso dovrebbe essere il verde, ma nel nostro esempio è il ciano. Riuscite a trovare un modo per rimediare e far sì che sembri esattamente l'immagine seguente? [Suggerimento: è un buon momento per usare le funzioni di forma].
![](colorwheel.png)
* Leggete il [libro di Josep Alver "L'interazione dei colori”](http://www.goodreads.com/book/show/111113.Interaction_of_Color) e usate i seguenti esempi di shader come pratica.
<div class="glslGallery" data="160505191155,160505193939,160505200330,160509131554,160509131509,160509131420,160509131240" data-properties="clickRun:editor,openFrameIcon:false,showAuthor:false"></div>
#### Nota sulle funzioni e sugli argomenti.
Prima di addentrarci nel capitolo successivo, fermiamoci e torniamo indietro. Osservate le funzioni negli esempi precedenti. Noterete un ```in``` prima di definire il tipo degli argomenti. Questo è un [*qualificatore*](http://www.shaderific.com/glsl-qualifiers/#inputqualifier) e in questo caso specifica che la variabile è solamente letta. Negli esempi futuri vedremo che è anche possibile definire argomenti come ```out``` o ```inout```. Quest'ultimo, ```inout```, è concettualmente simile a passare un argomento per referenza, il che ci dà la possibilità di modificare una variabile passata.
```glsl
int newFunction(in vec4 aVec4, // solo lettura
out vec3 aVec3, // solo scritture
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.

@ -68,7 +68,7 @@ green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue
* 色を表情豊かに変化させてください。なにか特定の感情を思い浮かべてみましょう。一番ふさわしいのは何色ですか? どのように現れてどのように消えていくのでしょう? もう1つ別の感情について考えて、ふさわしい色を選んでください。上記のサンプルの始まりと終わりの色をこの2つの感情の色に変えてください。次にシェイピング関数を使って色を滑らかに変化させましょう。
Robert Pennerは[イージング関数](http://easings.net/)と呼ばれる、コンピューターアニメーションでよく使われる一連の関数を開発しました。[このサンプル](../edit.html#06/easing.frag)を使って研究したりインスピレーションを得ることもできますが、一番良いのはあなた自身で関数を作ってみることでしょう。
Robert Pennerは[イージング関数](http://easings.net/)と呼ばれる、コンピューターアニメーションでよく使われる一連の関数を開発しました。[このサンプル](../edit.php#06/easing.frag)を使って研究したりインスピレーションを得ることもできますが、一番良いのはあなた自身で関数を作ってみることでしょう。
### グラデーションで遊ぶ

@ -1,7 +1,7 @@
## Colors
![Paul Klee - Color Chart (1931)](klee.jpg)
## 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.
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```.
@ -13,7 +13,7 @@ red.y = 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]```.
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]```.
The following lines show all the ways to access the same data:
@ -64,7 +64,7 @@ Check the following code at line 18 and see how we are using the absolute values
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.html#06/easing.frag) as research and inspiration but the best result will come from making your own transitions.
* 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
@ -126,6 +126,10 @@ Try the following exercises:
![](colorwheel.png)
* Read [Josep's Alvers book Interaction of Color](http://www.goodreads.com/book/show/111113.Interaction_of_Color) and use the following shaders examples as practice.
<div class="glslGallery" data="160505191155,160505193939,160505200330,160509131554,160509131509,160509131420,160509131240" data-properties="clickRun:editor,openFrameIcon:false,showAuthor:false"></div>
#### Note about functions and arguments
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.
@ -134,9 +138,8 @@ Before jumping to the next chapter lets stop and rewind. Go back and take loo
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.

@ -0,0 +1,2 @@
Familiarize yourself with how to express colors in shaders. The examples cover how to mix colors and beautifully animate them over time as well as conversion between two different models(RGB and HSB).
In GLSL, colors are simply just vectors, which means you can easily apply the concepts and techniques you learn here to other

@ -0,0 +1 @@
## Colors

@ -1 +0,0 @@
Add some references and ideas from this IQ article: http://iquilezles.org/www/articles/palettes/palettes.htm

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

@ -0,0 +1,107 @@
Add some references and ideas from this IQ article: http://iquilezles.org/www/articles/palettes/palettes.htm
### nicolas
* struct exist in GLSL : this is valid
```precision mediump float;
struct my_struct {
vec4 color;
};
uniform my_struct u_colors[2];
void main(void) {
gl_FragColor = u_colors[0].color;
}
```
[source](https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance/glsl/misc/shader-with-array-of-structs-uniform.html)
[NICO]
note: I had previously associated the name *accessor* to 'the way one can access the properties of an object'.
we can use those **accessors** independently ; the following code creates a clone *newColor* of the *color* vector by using a different accessor for each property.
```glsl
vec4 color = vec4( 1.,0.,0.5,1. );
vec4 newColor = vec4( color[0], color.g, color.z, color.q );
```
It is possible to combine the properties by **concatenating** different accessors:
if we need to use the ```.r```, ```.g``` and ```.b``` values of a 4 dimensions vector but don't need the ```.a``` (alpha) value, we can write:
```glsl
vec4 color = vec4( 1.,0.,0.5,1. );
vec4 newColor = vec4( color.rgb, 1.0 );
```
Which is the same as cloning each property ```.r```, ```.g``` and ```.b``` from ```color``` individually and dropping the last (```.a```).
In this case, ```color.rgb``` is interpreted as a vector of type ```vec3``` that contains the values ```.r```, ```.g``` and ```.b``` of the original ```vec4``` vector *color*.
The same goes for:
```glsl
vec4 color = vec4( 1.,0.,0.5,1. );
vec3 newColor = vec3( color.xy, 1.0 );
```
We use the values ```.x``` and ```.y``` from *color* to build a vector *newColors* of type ```vec3``` which ```.r``` and ```.g``` values will be the same as the *color* vector and ```.b``` value will be ```1.0```.
Last but not least, the order in which you **concatenate** the accessors matters.
If you want to build a vector from another vector but want to reverse the order of the properties, here's how you can write it:
```glsl
vec3 color = vec3( 1.0, 0.0, 0.5 );
vec3 newColor = color.bgr;
```
the *newColor* vector will copy *color*'s properties but instead of copying them in the "regular" order: ```.r```, ```.g``` and ```.b```,
it will copy them in the order defined by the concatenation: ```.b```, ```.g``` and ```.r```.
```glsl
color.r => 1.0
color.g => 0.0
color.b => 0.5
and
newColor.r => 0.5
newColor.g => 0.0
newColor.b => 1.0
```
On a side note, you can reuse the same accessor mutiple times and in whatever order in a concatenated accessor:
```glsl
color.rrr => vec3( 1.0 )
color.rrg => vec3( 1.0, 1.0, 0.0)
color.bgg => vec3( 0.5, 0.0, 0.0)
etc.
```
This results in the fact that, if the following is true:
```glsl
color.rgba = color.xyzw = color.stpq
```
these statements are not necessarily true:
```glsl
color.rgba != color.argb != color.rbga != color.abgr etc.
color.xyzw != color.wxyz != color.xzyw != color.wzyx etc.
color.stpq != color.qstp != color.sptq != color.qpts etc.
```
This is a powerful feature ; it allows to store the data in compact forms and manipulate them in very flexible ways.
Let's see a use case of the *compactness*: say you want to describe a rectangle, you can do so by using 2 ```vec2``` describing respectively the top left corner and the bottom right corner
or you can instead, use a single ```vec4``` which ```.xy``` **accessor** will return a ```vec2``` describing the top left corner, and which ```.zw``` **accessor** will return a ```vec2``` describing the bottom right corner.
[/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.
[NICO]
rephrased this:
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*.
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]

@ -1,2 +1,11 @@
- [Distance Transforms of Sampled Functions] (http://cs.brown.edu/~pff/papers/dt-final.pdf)
### nicolas
* after the pseudocode, explain why not using 'if' instead of step( threshold, value ) as this is (fucking) counter-intuitive :)
* L 61 'That way the ```vec2(0.0,0.0)```' should rather be : 'That way the ```vec2``` *tl*' to disambiguate it from br which is also a vec2
* 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'

@ -0,0 +1,293 @@
![Alice Hubbard, Providence, United States, ca. 1892. Photo: Zindman/Freemont.](froebel.jpg)
## Formes
Enfin! Tous ce que nous avons appris nous a mené jusqu'à ce moment!
Nous avons vu la plupart des bases, des types et des fonctions,
nous avons répété nos fonctions de formes à une dimension, il est temps de faire marcher tout ça ensemble et vous êtes paré!
Dans ce chapitre, vous apprendrez à dessiner des formes, de façon procédurale et en parallèle sur un GPU.
### Rectangle
Imaginons que nous avons un papier millimétré, comme à l'école, et nos devoirs consistent à dessiner un carré.
la taille de la feuille est 10x10 et le carré doit mesurer 8x8, comment faire?
![](grid_paper.jpg)
A priori nous allons colorier tout sauf: la première et la dernière rangée et la première et la dernière colonne, c'est bien ça?
En quoi est-ce lié aux shaders?
Chaque petit carré du papier millimétré est un thread (un pixel, ou fragment).
chaque petit carré connaît sa position, comme des coordonnées sur un échiquier.
Dans les chapitres précédents, nous avons appris à nous servir des valeurs normalisées, par exemple, nous avons mappé ces positions *x* et *y* vers les canaux *rouge* et *vert*.
Comme nos valeurs étaient normalisées entre 0.0 and 1.0, on pouvait les utiliser comme des couleurs, ou dans les fonctions de formes, ou dans les interpolations.
Mais à présent, comment utiliser ces valeurs *x* et *y* normalisées pour dessiner un carré au centre du canvas?
Commençons par utiliser un pseudocode se servant d'une condition ```if/else``` sur toute la taille du canvas.
Le procédé est très proche de la démarche que nous avons eu avec le papier millimétré.
```glsl
if ( (X SUPERIEUR A 1) AND (Y SUPERIEUR A 1) )
dessine en blanc
else
dessine en noir
```
Nous avons une meilleure idée du code qu'il va falloir produire, nous allons remplacer les ```if``` par des [```step()```](../glossary/?search=step)
et au lieu d'utiliser 10x10, nous utiliserons les valeurs *x* et *y* normalisées entre 0.0 et 1.0:
```glsl
uniform vec2 u_resolution;
void main(){
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(0.0);
// chaque appel à step() renverra soit: 1.0 (blanc), soit 0.0 (noir).
float gauche = step(0.1,st.x); // équivalent à: si( X supérieur à 0.1 )
float bas = step(0.1,st.y); // équivalent à: si( Y supérieur à 0.1 )
// multiplier gauche par bas revient à faire un AND logique.
color = vec3( gauche * bas );
gl_FragColor = vec4(color,1.0);
}
```
La fonction [```step()```](../glossary/?search=step), va dessiner tous les pixels dont la valeur des *x* est inférieure à 0.1 en noir (```vec3(0.0)```) et tous les autres en blanc (```vec3(1.0)```).
Le fait de multiplier ```gauche``` par ```bas``` est équivalent à l'opérateur logique ```AND``` ; si les deux opérantions (X<.1 et Y<.1) renvoient 1.0, le résultat sera 1.0, sinon, ce sera 0.0.
Cela nous permet de dessiner 2 lignes noires, une en bas et une à gauche du canvas.
[NDT]En règle générale et bien que ce ne soit pas interdit, il est déconseillé d'utiliser les ```if``` dans un shader.
ça peut paraître contre-intuitif mais la raison est simple, si on fait un ```if``` (ce qu'on appelle un *conditional branching*),
le programme va devoir évaluer les 2 branches de toutes façons et cette évaluation va ralentir (voire anéantir) le bénifice d'utiliser le GPU.
Une stratégie pour parer à ce problème est de structurer le code de manière à éliminer les conditions, donc les branches.
En l'occurrence, se servir du résultat (0 ou 1) de ```step()``` et le multiplier par une autre variable (la couleur par exemple).
Si le ```step()``` renvoie 1, la couleur se multipliera par 1 et restera la même, si le ```step()``` renvoie 0, la couleur se multipliera par 0 donc elle passe au noir.
C'est une technique que voue retrouverez souvent dans les shaders.[/NDT]
![](rect-01.jpg)
Dans l'exemple ci-dessus, nous répétons la même opération sur chaque axe gauche et bas.
Nous pouvons économiser quelques lignes de code en passant les deux valeurs *x* et *y* au [```step()```](../glossary/?search=step) simultanément au lieu de faire deux appels à ```step()``` séparés, ce qui resemble à ça:
```glsl
vec2 limites = step(vec2(0.1),st);
float pct = limites.x * limites.y;
```
Nous avons à présent deux limites de notre rectangle: gauche et bas. Occupons nous des deux autres: haut et droite, regardez le code suivant:
<div class="codeAndCanvas" data="rect-making.frag"></div>
Décommentez les *lignes 21-22* et notez comment nous inversons les coordonnées de ```st``` (*1.0 - st*) et réutilisons le même appel à [```step()```](../glossary/?search=step).
Le ```vec2 tr``` contient à présent les réponses du test pour le coin haut droit. C'est l'équivalent numérique de: "retourner la page et appliquer la même procédure".
![](rect-02.jpg)
Notez qu'aux *lignes 18 et 22*, tous les côtés sont multipliés entre eux, ce qui revient à écrire:
```glsl
vec2 bl = step(vec2(0.1),st); // bas-gauche
vec2 tr = step(vec2(0.1),1.0-st); // haut-droit
color = vec3(bl.x * bl.y * tr.x * tr.y);
```
Intéressant n'est ce pas?
Le principe de cette technique est de se servir de [```step()```](../glossary/?search=step) et des multiplications comme d'opérateurs logiques et de retourner les coordonnées pour traiter les deux côtés de l'image.
Avant d'aller plus loin, essayez les choses suivantes:
* Changer la taille et les proportions du rectangle.
* Utilisez [```smoothstep()```](../glossary/?search=smoothstep) au lieu de [```step()```](../glossary/?search=step). Notez comme les arêtes passent d'un rendu net à flou.
* Réimplémentez les conditions en utilisant [```floor()```](../glossary/?search=floor).
* Conservez votre version préférée et faites-en une version réutilisable, si possible une fonction flexible et efficace (pas de *if* par exemple).
* Créez un fonction qui dessine uniquement l'extérieur du rectangle.
* Comment placer et déplacer plusieurs rectangles sur le canvas? si vous trouvez la réponse, tentez de créer une composition à la [Piet Mondrian](http://en.wikipedia.org/wiki/Piet_Mondrian).
![Piet Mondria - Tableau (1921)](mondrian.jpg)
### Cercles
Dessiner des carrés sur du papier millimétré est assez simple mais les cercles demandent un changement d'approche, notamment lorsqu'on doit traiter une masse de *pixels*.
Une solution est de *re-mapper* le système de coordonnées de manière à pouvoir utiliser la fonction [```step()```](../glossary/?search=step) pour dessiner un cercle.
Comment?
Retournons à notre cours de math et à notre papier millimétré, on utilise un compas, on lui donne le bon rayon, on pose la pointe au centre du cercle et on trace le contour du cercle.
![](compass.jpg)
Traduire cette démarche dans un shader où chaque carré du papier est un pixel revient à *demander* à chaque pixel (ou thread ou fragment), s'il est à l'intérieur ou à l'extérieur du cercle.
Pour ce faire, nous allons donc calculer la distance de chaque fragment au centre de notre cercle.
![](circle.jpg)
Il existe plusieurs façons de calculer une distance. La plus simple est d'utiliser la fonction [```distance()```](../glossary/?search=distance), qui - en interne - calcule la longueur de la différence entre les deux points passés en arguments (dans notre cas, les coordonnées du pixel et la position du centre).
La fonction ```length()``` est simplement un raccourci pour [l'équation de l'hypoténuse](http://en.wikipedia.org/wiki/Hypotenuse) qui utilise la racine carrée [```sqrt()```](../glossary/?search=sqrt) de la somme des différences en *x* et *y*, au carré.
![](hypotenuse.png)
On peut donc utiliser indifféremment [```distance()```](../glossary/?search=distance), [```length()```](../glossary/?search=length) ou [```sqrt()```](../glossary/?search=sqrt) pour calculer la distance du pixel au centre du canvas.
Le code suivant contient ces trois fonctions et démontre sans surprise que les trois renvoient le même résultat.
* Commentez et décommentez les blocs pour utiliser les différentes manières de calculer la distance.
<div class="codeAndCanvas" data="circle-making.frag"></div>
Dans l'exemple ci-dessus, nous mappons la distance au centre du canvas sur la Valeur (la luminosité) du pixel de sortie.
Plus on est proche du centre, moins la distance est grande donc plus le pixel est sombre.
Notez que les valeurs ne montent pas énorménent (jusqu'au blanc par exemple) parce que, la plus grande distance entre un pixel et le centre ( ```vec2(0.5, 0.5)``` ) dépasse péniblement 0.5.
Prenez un moment pour observer et demandez vous:
* Que peut-on déduire de ça?
* Comment peut-on s'en servir pour dessiner un cercle?
* Modifiez le code suivant pour faire tenir le dégradé complet du cercle à l'intérieur du canvas.
[NDT]en fait, la plus grande distance entre un pixel et le centre est: ```sqrt( 2.0 ) * .5``` soit environ *0.7071* [/NDT]
### Champ de distance (Distance field)
Nous pouvons penser l'exemple ci-dessus comme étant une carte d'élévations ou les parties sombres seraient plus élevées.
Le dégradé du cercle ressemble à ce que serait un cone.
Imaginez vous au sommet de ce cone, la distance horizontale vers les bords du cone serait 0.5, elle est constante dans toutes les directions.
En choisissant à quelle hauteur on peut *couper* le cone, on obtiendra un disque plus ou moins grand.
![](distance-field.jpg)
En somme, on utilise une ré-interprétation de l'espace, en se basant sur la distance au centre plutôt que sur les coordonnées des pixels, pour créer des formes.
Cette technique s'appelle un "champ de distances" (Distance Field) et s'applique dans de nombreux contextes allant du dessin de contours à la 3D.
Essayez les choses suivantes:
* Utilisez [```step()```](../glossary/?search=step) pour passer toutes les valeurs supérieures à 0.5 en blanc et toutes les autres en noir.
* Inverser les couleurs d'avant plan et d'arrière plan.
* Utilisez [```smoothstep()```](../glossary/?search=smoothstep) et changez les paramètres pour ajouter un contour flou au cercle.
* Quand vous obtenez un résultat satisfaisant, créez une fonction que vous pourrez réutiliser.
* Ajoutez de la couleur.
* Pouvez-vous animer le cercle pour qu'il grossisse et rapetisse? pour qu'il simule un battement de coeur? (les animations du chapitre précédent vous aideront).
* Comment déplacer ce cercle? pouvez vous le déplacer et placer plusieurs cercles sur le même canvas?
* Que se passe-t'il quand on combine plusieurs champs de distances en utilisant différentes fonctions et opérations?
```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)));
```
* Faites trois compositions avec ces techniques, si elles bougent, c'est encore mieux!
#### Pour la boîte à outils
La fonction [```sqrt()```](../glossary/?search=sqrt) - comme toutes les fonctions qui en dépendent - est assez gourmande en ressources.
Voici autre une technique permettant de créer un champ de distances basée sur la fonction [```dot()```](../glossary/?search=dot).
<div class="codeAndCanvas" data="circle.frag"></div>
[NDT]```dot()``` renvoie le produit scalaire de deux vecteurs: ```dot(a,b)=a.x * b.x + a.y * b.y;```[/NDT]
### Propriétés utiles des champs de Distances
![Zen garden](zen-garden.jpg)
Les champs de distance permettent de dessiner à peu près n'importe quoi.
Evidemment, plus la forme est complexe, plus l'équation sera complexe mais une fois qu'on a la formule d'une forme en particulier, il devient assez simple de la combiner avec d'autres et/ou de lui appliquer des effets comme des bords lissés, ou plusieurs contours.
C'est pourquoi les champs de distances sont utilisés pour le rendu des polices de caractères: [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) et [comme expliqué au chapitre 7 de "iPhone 3D Programming", OReilly](http://chimera.labs.oreilly.com/books/1234000001814/ch07.html#ch07_id36000921).
Prenez le code suivant:
<div class="codeAndCanvas" data="rect-df.frag"></div>
On commence par déplacer le système de coordonnées au centre et à le diviser par deux pour obtenir des valeurs comprises entre -1 et 1.
A la *ligne 24*, nous visualisons le champ de distances grâce à la fonction [```fract()```](../glossary/?search=fract) ce qui nous permet de mieux voir le motif qu'il crée.
Le motif du champ de distances se répète en cercles concentriques, à la manière d'un jardin zen.
Regardons la formule du champ de distances *ligne 19*. Nous calculons la distance entre chaque position et la coordonnée ```( .3,.3 )``` ( entre ```st``` et le vecteur ```vec2(.3)```) pour chaque quadrant, c'est à ça que sert l'appel à [```abs()```](../glossary/?search=abs).
Si vous décommentez la *ligne 20*, vouz noterez que nous combinons les distances à ces 4 points en utilisant la fonction [```min()```](../glossary/?search=min) contre 0, ce qui produit un nouveau motif.
[NDT]en fait il n'y a qu'un seul point, pas '4', celui en haut à droite mais il est *reflété* dans les 3 autres *quadrants* du fait qu'on a changé la taille de l'espace *ligne 16*[NDT]
Essayez à présent de décommenter la *ligne 21*, nous utilisons cette fois la fonction [```max()```](../glossary/?search=max).
Le résultat est un rectangle aux bords arrondis.
Remarquez comme les anneaux du champ de distance deviennent de plus en plus lissse à mesure qu'ils s'éloignent du centre.
Enfin, décommentez les *ligne 27 à 29* une par une pour comprendre les différentes utilisations du champ de distances.
### Formes polaires
![Robert Mangold - Untitled (2008)](mangold.jpg)
Au chapitre des couleurs, nous avons projeté (mappé) des coordonnées cartésiennes sur des coordonnées polaires en calculant un *rayon* et un *angle* entre chaque pixel et le centre grâce à la formule suivante:
```glsl
vec2 pos = vec2(0.5)-st;
float r = length(pos)*2.0;
float a = atan(pos.y,pos.x);
```
Nous avons ré-utilisé une partie de cette formule au début du chapitre pour dessiner un cercle.
Nous calculions la distance en nous servant de [```length()```](../glossary/?search=length).
Maintenant que nous en savons plus sur les champs de distances, nous pouvons dessiner de nouvelles formes grâce aux coordonnées polaires.
La technique est un peu restrictive mais très simple: elle consiste à changer la valeur du *rayon* en fonction de l'*angle* pour obtenir une variété de formes.
Comment moduler cette longueur? Avec des fonctions de formes bien sûr!
Ci-dessous, vous trouverez les mêmes fonctions dans un espace cartésien et dans un espace polaire (entre les *lignes 21 et 25* du shader).
Décommentez les fonctions une par une dans les deux démos pour comprendre les relations qui existent entre les deux systèmes de coordonnées.
<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>
Essayez de:
* Animer les formes.
* Combiner différentes fonctions de formes pour *creuser des trous* dans les formes pour faire des fleurs, des flocons et des engrenages.
* Utilisez la fonction ```plot()``` du chapitre sur les fonctions de forme pour ne garder que le contour.
### Combinatoires
Nous venons de voir comment moduler le rayon d'un cercle en fonction d'un angle en utilisant la fonction [```atan()```](../glossary/?search=atan) pour dessiner différentes formes.
Voyons maintenant comment utiliser ```atan()``` avec un champ de distances de façon à pouvoir utiliser les effets qu'ils permettent.
L'astuce c'est d'utiliser le nombre de côtés d'un polygone régulier pour construire un champ de distances dans un espace polaire.
Pour plus d'informations, vous pouvez vous référer [au code suivant](http://thndl.com/square-shaped-shaders.html) par [Andrew Baldwin](https://twitter.com/baldand).
<div class="codeAndCanvas" data="shapes.frag"></div>
* En reprenant cet exemple, créez une fonction qui reçoit une position et un nombre de côtés et retourne la valeur du champ de distance correspondant.
* Mélangez les champs de distances en utilisant [```min()```](../glossary/?search=min) et [```max()```](../glossary/?search=max).
* Choisissez un logo géométrique et reproduisez le avec des champs de distance.
Félicitations!
Vous avez fait le plus dur!
Faites une pause et laissez décanter ces nouveaux concepts.
Dessiner des formes dans une API de dessin, c'est facile mais ici c'est une autre histoire.
Au pays des shaders, dessiner des formes géométriques est un peu tordu et s'imposer la disciple nécessaire à la compréhension de ce paradigme est épuisant.
Maintenant que vous savez comment dessiner des formes, je suis sûr que ça va vous donner des idées.
Au prochain chapitre, nous apprendrons à déplacer, à appliquer des rotations et à changer d'échelle pour créer des compositions!

@ -0,0 +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!

@ -1,7 +1,7 @@
## Shapes
![Alice Hubbard, Providence, United States, ca. 1892. Photo: Zindman/Freemont.](froebel.jpg)
## 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.
### Rectangle
@ -86,7 +86,7 @@ Before going forward, try the following exercises:
* How do you think you can move and place different rectangles in the same billboard? If you figure out how, show off your skills by making a composition of rectangles and colors that resembles a [Piet Mondrian](http://en.wikipedia.org/wiki/Piet_Mondrian) painting.
![Piet Mondria - Tableau (1921)](mondrian.jpg)
![Piet Mondrian - Tableau (1921)](mondrian.jpg)
### Circles

@ -0,0 +1 @@
Let's look at how to draw simple shapes in a parallel procedural way. In a nutshell, all you need to do is to determine if each pixel belongs to the shape you want to draw or not, and apply different colors accordingly. You can use coordinate system like a grid paper to draw rectangles and squares. We'll look at more advanced concept called distance field to draw more complex shapes.

@ -0,0 +1 @@
## Shapes

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

@ -0,0 +1 @@
<div class="glslGallery" data="160414041142,160414040957,160414040804" data-properties="clickRun:editor,hoverPreview:false"></div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

@ -0,0 +1,126 @@
## Matrices 2D
<canvas id="custom" class="canvas" data-fragment-url="matrix.frag" width="700px" height="200px"></canvas>
### Translation
Au chapitre précédent, nous avons vu comment créer des formes, l'astuce pour déplacer une forme consistait à déplacer le système de coordonnées lui-même.
Nous opérions cette translation en ajoutant un vecteur 2d à la variable ```st``` contenant la position du fragment ce qui avait pour conséquence de décaler la position de l'ensemble des fragments en cours de traitement.
![](translate.jpg)
Un exemple sera sans doute plus explicite:
* Décommentez la ligne 35 du code ci-dessous pour voir le système de coordonnées bouger.
<div class="codeAndCanvas" data="cross-translate.frag"></div>
Essayez l'exercice suivant:
* servez vous d'```u_time``` et des fonctions de formes pour déplacer la croix de façon intéressante.
Pensez à un type de mouvement et tentez de l'appliquer à la croix. Prenez des exemples de la "vraie vie", ça aide. par exemple un mouvement de vagues, un pendule, une balle qui rebondit, un vélo qui freine...
### Rotations
Pour effectuer une rotation, nous devons transformer tout le système de coordonnées.
Pour nous aider, nous allons utiliser un objet [matrix](http://en.wikipedia.org/wiki/Matrix_%28mathematics%29) qui permet de manipuler une matrice de transformation 2d.
Une matrice est un objet organisé en 'grille', elle se compose de colonnes et de rangées de chiffres.
Lorsqu'on multiplie un Vecteur par une matrice, la matrice exécute une série d'opérations, dans un certain ordre et *transforme* le Vecteur en fonction des valeurs qu'elle contient.
[NDT]C'est pourquoi on les appelle souvent des *matrices de transformations*, la plupart des APIs graphiques - tout support confondu - proposent une matrice de transformation 2D, 3D ou 4D.
Les matrices permettent de stocker plusieurs types de transformations (souvent: translation, rotation et échelle) dans un objet compact et utilisable avec des vecteurs.[/NDT]
pour en savoir plus, référez vous à l'article Wikipédia sur les matrices: [![article Wikipédia sur les matrices](matrixes.png)](https://fr.wikipedia.org/wiki/Matrice_(math%C3%A9matiques))
Le GLSL supporte nativement les matrices à deux, trois et quatre dimensions: [```mat2```](../glossary/?search=mat2) (2x2), [```mat3```](../glossary/?search=mat3) (3x3) et [```mat4```](../glossary/?search=mat4) (4x4).
Le GLSL surcharge certains opérateurs, notamment la multiplication et offre des fonctions spécifiques comme [```matrixCompMult()```](../glossary/?search=matrixCompMult), qui effectue un produit scalaire des composants des matrices passées en argument.
Les matrices sont très utiles et permettent d'obtenir des transformations et des comportements spécifiques.
Par exemple, on peut utiliser une matrice pour appliquer une translation à un vecteur:
![](3dtransmat.png)
[NDT]la matrice est à gauche, les valeurs de translation *tx* et *ty* (la quantité de déplacement en x et en y) sont stockées à un endroit précis de la matrice (troisième colonne, rangées 1 et 2). le vecteur 2D que nous voulons transformer est au centre, le point entre les deux représente une multiplication et le résultat est à droite[/NDT]
Une matrice permet également d'effectuer une rotation:
![](rotmat.png)
[NDT]Notez que les valeurs de rotations (*cos()* et *sin()*) sont décrites à un endroit (colonnes, rangées) différent des valeurs de translation (*tx* et *ty*).
C'est ce qui permet de stocker plusieurs transformations dans la même matrice.[/NDT]
Le code suivant montre comment construire une matrice de rotation 2D.
Cette fonction s'appuie sur [la formule suivante](https://fr.wikipedia.org/wiki/Matrice_de_rotation) pour faire pivoter un vecteur 2D autour de l'origine du système d ecoordonnées ; le point ```vec2(0.0)```.
```glsl
mat2 rotate2d(float _angle){
return mat2(cos(_angle),-sin(_angle),
sin(_angle),cos(_angle));
}
```
Cett manière d'effectuer un rotation (autour de l'origine) ne marche pas avec l'approche que nous avons eu jusqu'à présent pour dessiner les formes.
En effet notre croix est dessinée au centre du canvas (le point ```vec2(0.5)```) alors sque la rotation se fait autour de l'origine (le point ```vec2(0.0)```).
Donc, avant d'effectuer la rotation, nous devons déplacer la forme du `centre` vers l'origine ```vec2(0.0)```, appliquer la rotation puis re-déplacer la forme au `centre` du canvas.
![](rotate.jpg)
Le code ressemble à ça:
<div class="codeAndCanvas" data="cross-rotate.frag"></div>
Essayez les choses suivantes:
* Décommentez la ligne 45 du code ci-dessus et observez ce qui se passse.
* Commentez les translations avant et après la rotation aux lignes 37 et 39, observez ce qui se passe.
* Utilisez les rotations pour améliorer l'animation basée sur les translations que vous avez fait plus haut.
### Echelle
Nous avons vu que les matrices permettent de déplacer et de faire pivoter les objets dans l'espace ou plus exactement de déplacer l'origine et de lui appliquer une rotation avant de dessiner une forme.
Si vous avez déjà fait de la 3D ou que vous vous êtes déjà servi des méthodes push et pop des matrices dans Processing, vous savez qu'on peut également se servir de matrices pour redimensionner un objet.
![](scale.png)
Voici à quoi ressemble une matrice 2D de mise à l'échelle:
```glsl
mat2 scale(vec2 _scale){
return mat2(_scale.x,0.0,
0.0,_scale.y);
}
```
<div class="codeAndCanvas" data="cross-scale.frag"></div>
Pour mieux comprendre comment ça marche, essayez les choses suivantes:
* Décommentez la ligne 42 du code ci-dessus pour visualiser la mise à l'échelle en couleur.
* Regardez ce qui se passe quand vous commentez les translations avant et après la mise à l'échelle aux lignes 37 et 39.
* Essayez de combiner rotation et mise à l'échelle dans une seule matrice. Attention, l'ordre des opérations est important ; multipliez d'abord les matrices entre elles avant de multiplier le vecteur par la matrice finale.
* A présent que vous savez dessiner des formes et les transformer, essayez de faire une petite composition.
Reprenez le design d'une de ces [fausses UI et HUD (Heads Up Display)](https://www.pinterest.com/patriciogonzv/huds/).
Servez vous du sketch ShaderToy suivant (par [Ndel](https://www.shadertoy.com/user/ndel)) comme point de départ et/ou comme référence.
<iframe width="800" height="450" frameborder="0" src="https://www.shadertoy.com/embed/4s2SRt?gui=true&t=10&paused=true" allowfullscreen></iframe>
### Autres utilisations des matrices: l'espace colorimétrique YUV
[YUV](https://fr.wikipedia.org/wiki/YUV) est un espace colorimétrique utilisé pour l'encodage de photographies et de vidéos analogues.
Il prend en compte ce que perçoit l'oeil humain de la lumière et modifie les plages du spectre lumineux pour s'y adapter.
Dans le code suivant, nous utilisons une matrice pour opérer la conversion d'un espace colorimétrique à l'autre (RGB est l'espace colorimétrique par défaut)
<div class="codeAndCanvas" data="yuv.frag"></div>
Comme vous pouvez le voir, nous traitons les couleurs comme des vecteurs et les multiplions par une matrice.
Nous avons *déplacé* les valeurs de la couleur comme nous aurions déplacé une vecteur de position dans l'espace.
Dans ce chapitre, nous avons vu comment utiliser une matrice pour déplacer, faire pivoter et redimensionner un vecteur.
Ces transformations sont essentielles lorsqu'on veut agencer les formes que nous avons appris à créer au chapitre précédent.
Au chapitre suivant nous allons utiliser ce que nous venons de voir pour créer des motifs procéduraux.
Vous verrez que créer des répétitions et des variations peut être très gratifiant.

@ -0,0 +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.

@ -0,0 +1,2 @@
Matrix is a very powerful tool for manipulating vectors. By mastering how to use matrices, you can freely translate, scale and rotate shapes. Since the technique can be equally applied to anything expressed by vectors, we will look at many more advanced use of matrices later in this book.
Matrices may look complex at a first glance, but you'll find it very handy and useful as you get used to the concept. Let's practice here and learn basics with simple examples.

@ -0,0 +1 @@
## 2D Matrices

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

@ -2,7 +2,7 @@
因为着色器按一个个像素执行,那么无论你重复一个图形多少次,计算的数量仍然是个常数。
[ ![Nina Warmerdam - The IMPRINT Project (2013)](warmerdam.jpg) ](../edit.html#09/dots5.frag)
[ ![Nina Warmerdam - The IMPRINT Project (2013)](warmerdam.jpg) ](../edit.php#09/dots5.frag)
本章中我们将综合我们目前所学的并应用在画布上。和前几章一样我们的策略依然基于乘以空间坐标0到1之间这样我们的画的在0到1之间的图形就会重复地形成网格。
@ -44,7 +44,7 @@ void main(){
* 通过组合不同的形状重新创造更复杂的图案。
<a href="../edit.html#09/diamondtiles.frag"><canvas id="custom" class="canvas" data-fragment-url="diamondtiles.frag" width="520px" height="200px"></canvas></a>
<a href="../edit.php#09/diamondtiles.frag"><canvas id="custom" class="canvas" data-fragment-url="diamondtiles.frag" width="520px" height="200px"></canvas></a>
* 结合多层图案来制作你自己的 [Scottish Tartan Patterns](https://www.google.com/search?q=scottish+patterns+fabric&tbm=isch&tbo=u&source=univ&sa=X&ei=Y1aFVfmfD9P-yQTLuYCIDA&ved=0CB4QsAQ&biw=1399&bih=799#tbm=isch&q=Scottish+Tartans+Patterns).
@ -84,7 +84,7 @@ ____我们需要两段来解决这个问题____
* 试着结合 ```x``` 和 ```y``` 轴的偏移来得到下面这样的效果:
<a href="../edit.html#09/marching_dots.frag"><canvas id="custom" class="canvas" data-fragment-url="marching_dots.frag" width="520px" height="200px"></canvas></a>
<a href="../edit.php#09/marching_dots.frag"><canvas id="custom" class="canvas" data-fragment-url="marching_dots.frag" width="520px" height="200px"></canvas></a>
## Truchet 瓷砖
@ -110,7 +110,7 @@ ____我们需要两段来解决这个问题____
* 想想其他能用这章原理的案例,不一定是图案. (例: 易经卦)
<a href="../edit.html#09/iching-01.frag"><canvas id="custom" class="canvas" data-fragment-url="iching-01.frag" width="520px" height="200px"></canvas></a>
<a href="../edit.php#09/iching-01.frag"><canvas id="custom" class="canvas" data-fragment-url="iching-01.frag" width="520px" height="200px"></canvas></a>
## 制定自己的规则

@ -0,0 +1,182 @@
## Motifs
Les shaders sont exécutés au pixel et quel que soit le nombre de répétitions d'une forme, le nombre d'opérations effectuées restera constant.
Cela signifie que les fragments shaders sont tout à fait indiqués pour la création de motifs répétitifs ; des *pavages* du plan.
[ ![Nina Warmerdam - The IMPRINT Project (2013)](warmerdam.jpg) ](../edit.php#09/dots5.frag)
Dans ce chapitre, nous allons mettre en application tout ce que nous avons vu jusqu'à présent et le répéter sur le canvas.
Comme dans les chapitres précédents, notre stratégie consistera à multiplier les coordonnées pour que les formes que nous dessinons restent dans un espace normalisé entre 0 et 1.
Le fait de multiplier les coordonnées du fragment en X et en Y créera une *grille* et le fait de diviser les coordonnées *étirera* une portion du canvas.
*"The grid provides a framework within which human intuition and invention can operate and that it can subvert.
Within the chaos of nature patterns provide a constrast and promise of order.
From early patterns on pottery to geometric mosaics in Roman baths, people have long used grids to enhance their lives with decoration."* [*10 PRINT*, Mit Press, (2013)](http://10print.org/)
Pour commencer, rappelons nous de la méthode [```fract()```](../glossary/?search=fract).
Elle retourne la partie fractionnelle d'un chiffre, ce qui revient à considérer ```fract()``` comme le modulo de 1 ([```mod(x,1.0)```](../glossary/?search=mod)).
Autrement dit, [```fract()```](../glossary/?search=fract) retourne les chiffres après la virgule.
Notre variable normalisée (```st```) va déjà de 0.0 à 1.0 donc il n'est pas très judicieux d'écrire quelque chose comme:
```glsl
void main(){
vec2 st = gl_FragCoord.xy/u_resolution;
vec3 color = vec3(0.0);
st = fract(st);
color = vec3(st,0.0);
gl_FragColor = vec4(color,1.0);
}
```
En revanche, si nous multiplions la valeur de ```st``` par 3, l'utilisation de ```fract()``` nous permettra d'obtenir trois séries de valeurs normalisées entre 0 et 1:
la première série correspondra au moment où ```st``` se trouve entre 0 et 1, la seconde série correspondra au moment où ```st``` se trouve entre 1 et 2 et la troisième série correspondra au moment où ```st``` se trouve entre 2 et 3.
[NDT]Une fois multiplié par 3, et au lieu de passer de 0 à 1 en X et Y, ```st``` passera de 0 à **3** en X et Y.
Si nous utilisons ```st * 3.0``` tel quel, sa valeur va vite dépasser 1 et nous ne pourrons plus nous en servir comme nous l'avons fait jusqu'à présent ; il ne sera plus normalisé entre 0 et 1.
Si on utilise seulement la partie fractionnelle, on retombe toujours dans un espace normalisé puisque la valeur de ```fract()``` (les chiffres après le virgule) sera toujours comprise entre 0 et 1.
Voici un exemple des valeurs respectives de ```st```, ```st * 3``` et ```fract( st * 3 )```.
```glsl
premier bloc
st = 0.00 | st * 3 = 0.00 | fract( st * 3 ) = 0.00
st = 0.10 | st * 3 = 0.30 | fract( st * 3 ) = 0.30
st = 0.20 | st * 3 = 0.60 | fract( st * 3 ) = 0.60
st = 0.30 | st * 3 = 0.90 | fract( st * 3 ) = 0.90
second bloc
st = 0.40 | st * 3 = 1.20 | fract( st * 3 ) = 0.20
st = 0.50 | st * 3 = 1.50 | fract( st * 3 ) = 0.50
st = 0.60 | st * 3 = 1.80 | fract( st * 3 ) = 0.80
troisième bloc
st = 0.70 | st * 3 = 2.10 | fract( st * 3 ) = 0.10
st = 0.80 | st * 3 = 2.40 | fract( st * 3 ) = 0.40
st = 0.90 | st * 3 = 2.70 | fract( st * 3 ) = 0.70
st = 1.00 | st * 3 = 3.00 | fract( st * 3 ) = 1.00
```
On voit bien que sur le premier bloc, la valeur ```st * 3``` est égale à ```fract( st * 3 )``` mais dès le second *bloc*, ```st * 3``` dépassse 1 alors que ```fract( st * 3 )``` reste toujours compris entre 0 et 1.
[/NDT]
<div class="codeAndCanvas" data="grid-making.frag"></div>
Essayons de dessiner quelque chose dans chaque sous-espace en décommentant la ligne 27.
Comme nous ne changeons pas le *ratio* (le rapport largeur/hauteur) en x et y, la forme ne change pas après la multiplication de taille et notre forme s'affiche correctement ; notre cercle est bien circulaire.
Essayez les choses suivantes pour mieux comprendre:
* Changez le facteur de multiplication des coordonnées ```st```, essayez des valeurs inférieures à zéro et des valeurs différentes en X et Y.
* Créez un fonction réutilisable pour cette manipulation.
* Divisez l'espace en 3 lignes et trois colonnes.
Trouvez un moyen de connaître la case dans laquelle se trouve le fragment en cours de traitement et changez la forme dessinée dans la case en fonction de ça.
Essayez de faire un morpion.
### Appliquer une matrice à l'intérieur d'une cellule
Sachant que chaque subdivision est une reproduction du motif original, nous pouvons appliquer une matrice de transformation pour déplacer, pivoter ou redimensionner l'espace dans chaque cellule.
<div class="codeAndCanvas" data="checks.frag"></div>
* Pensez à quelques façons intéressantes d'animer les couleurs et les formes de ce motif. Faites-en trois versions.
* Créez des motifs plus complexes en combinant plusieurs formes.
[![](diamondtiles-long.png)](../edit.php#09/diamondtiles.frag)
* Combinez différentes couches de motifs pour composer votre propre [Tartan écossais](https://fr.wikipedia.org/wiki/Tartan).
[ ![Vector Pattern Scottish Tartan par Kavalenkava](tartan.jpg) ](http://graphicriver.net/item/vector-pattern-scottish-tartan/6590076)
### Décaler les motifs
Imaginons que nous voulions reproduire un motif *mur de briques*. En regardant le mur, nous constatons que chaque rangées est décalée de moitié par rapport à la précédente.
Comment pourrions-nous faire ça?
![](brick.jpg)
En premier lieu, nous devons savoir si la rangée sur laquelle se trouve notre fragment est paire ou impaire.
Nous pourrons ensuite utiliser cette information pour savoir si on doit ou non se décaler sur l'axe X.
Pour déterminer si notre fragment est sur une ligne paire ou impaire, nous allons nous servir du résultat du modulo [```mod()```](../glossary/?search=mod) de ```2.0```.
Si le modulo 2 est inférieur à 1, nous sommes sur une ligne paire, s'il est supérieur ou égal à 1, nous sommes sur une ligne impaire.
Pour illustrer l'effet du modulo, regardez la formule suivante et décommentez les deux dernières lignes.
<div class="simpleFunction" data="y = mod(x,2.0);
// y = mod(x,2.0) < 1.0 ? 0. : 1. ;
// y = step(1.0,mod(x,2.0));"></div>
On peut utiliser un [opérateur ternaire](https://fr.wikipedia.org/wiki/Op%C3%A9rateur_(informatique)) pour vérifier si le modulo ([```mod()```](../glossary/?search=mod)) renvoie une valeur inférieure à 1 (ligne 2)
ou bien on peut se servir d'un [```step()```](../glossary/?search=step) qui renvoie le même résultat plus vite.
Pourquoi? Bien qu'il soit difficile de dire comment chaque carte graphique compile et optimise le code, on peut partir du principe que les fonctions natives sont plus rapides que les fonctions personnalisées.
Chaque fois que vous pouvez utiliser une fonction native, faites le!
[NDT]En fait un opérateur ternaire est un ```if``` déguisé, le programme est obligé de créer et d'évaluer les deux branches du ```if``` ce qui ralentit son exécution. En l'occurrence, on pourrait écrire:
```glsl
y = floor( mod( x, 2.0 ) );
```
qui renverra également 0 si le modulo est inférieur à 1 et 1 si le modulo est compris entre 1 et 2. la différence étant qu'il n'y a besoin de charger qu'une seule valeur en mémoire contre 2 pour un step().
on pourrait même se dispenser du ```floor``` en utilisant un ```cast``` (*transtypage*) en ```int``` (nombre entier):
```glsl
y = float( int( mod( x, 2.0 ) ) );
```
lorsqu'on *transtype* un ```float``` en ```int``` les chiffres après la virgule sont ignorés ce qui revient à appeler la méthode ```floor``` (en revanche, on doit re-caster le résultat en ```float```).
[/NDT]
Maintenant que nous avons un moyen de déterminer si on a un chiffre pair ou impair, on peut s'en servir pour décaler les rangées impaires et obtenir notre *mur de briques*.
Ligne 14, nous avons une fonction qui *détecte* les rangées impaires et leur ajoute un décalage de 0.5 en ```x```.
Notez que pour les rangées paires, le résultat sera ```0.0``` et multiplier ```0.0``` par un décalage de ```0.5``` donnera un décalage de ```0.0```.
Sur les rangées impaires, le résultat sera ```1.0``` qui, multiplié par ```0.5```, décalera la position ```st``` de ```0.5``` sur l'axe des ```x```.
Essayez à présent de commenter la ligne 32, cela va changer le *ratio* (rapport entre largeur et hauteur) et *étirer* les coorodnnées pour produire une brique *moderne*.
En décommentant la ligne 40, on peut visualiser la distorsion grâce aux canaux rouge et vert.
<div class="codeAndCanvas" data="bricks.frag"></div>
* Essayez d'animer le motif en faisant varier la quantité de décalage en fonction du temps.
* Créez une autre animation où les rangées paires bougent vers la droite et les rangées impaires bougeant vers la gauche.
* Pouvez vous appliquer cet effet sur les colonnes?
* Essayez de combiner les décalages en ```x``` et ```y``` pour obtenir quelque chose comme ça:
<a href="../edit.php#09/marching_dots.frag"><canvas id="custom" class="canvas" data-fragment-url="marching_dots.frag" width="520px" height="200px"></canvas></a>
## Pavage de Truchet
Maintenant que que nous avons vu comment déterminer si une cellule est sur une ligne ou une colonne paire ou impaire, il nous est possible de réutiliser un motif en fonction de sa position.
Prenons le [pavage de Truchet](http://en.wikipedia.org/wiki/Truchet_tiles) [+](http://jean-luc.bregeon.pagesperso-orange.fr/Page%200-27.htm) où un élément simple est présent sous quatre formes:
![](truchet-00.png)
En changeant de motif d'une case à l'autre, on peut construire une infinité de pavages complexes.
![](truchet-01.png)
Regardez attentivement la fonction ```rotateTilePattern()```, qui subdivise l'espace en quatre cellules et assigne une rotation à chacune.
<div class="codeAndCanvas" data="truchet.frag"></div>
* Commentez / décommentez et dupliquez les lignes 69 à 72 pour composer de nouveaux motifs.
* Remplacez le triangle blanc par une autre forme: demi cercle, carré pivoté ou lignes.
* Créez d'autres motifs suivant la règle *pair/impair*.
* Variez les propriétés affectées par l'ordre *pair/impair* des cellules.
* Pensez à quelque chose d'autre qui ne soit pas nécessairement un pavage du plan et où vous pourriez appliquer les principes vus dans cette section (exemple: [les Hexagrammes YI Jing](https://fr.wikipedia.org/wiki/Hexagramme_Yi_Jing))
<a href="../edit.php#09/iching-01.frag"><canvas id="custom" class="canvas" data-fragment-url="iching-01.frag" width="520px" height="200px"></canvas></a>
## Créer ses propres pavages
Créer des motifs procéduraux est un exercice cérébral consistant à trouver un ensemble minimal d'éléments réutilisables.
C'est une pratique très ancienne, en tant qu'espèce, nous avons utilisé les grilles et les motifs pour décorer les textiles, les sols et les objets depuis la nuit des temps.
Des frises grecques aux lattices chinoises, le plaisir des variations et des répétitions est une grande source d'inspiration.
Prenez le temps de vous intéresser aux [motifs](https://www.pinterest.com/patriciogonzv/paterns/) [ornementaux](https://archive.org/stream/traditionalmetho00chririch#page/130/mode/2up)
et constatez que de tout temps, artistes et designers ont navigué entre un ordre prédictible et les variations, accidentelles et chaotiques.
Des motifs islamiques aux textiles africains, nous disposons d'un univers de motifs à explorer.
![Franz Sales Meyer - A handbook of ornament (1920)](geometricpatters.png)
Ce chapitre clos le dessin algorithmique. Dans les chapitres suivants, nous apprendrons à ramener un peu d'entropie et à produire des designs génératifs.

@ -0,0 +1,119 @@
## Motivi
Siccome i programmi shader sono eseguiti pixel per pixel non importa quante volte voi ripetiate una forma, infatti il numero dei calcoli rimane costante. Questo significa che i fragment shader sono particolarmente adatti per creare dei motivi ripetitivi.
[ ![Nina Warmerdam - The IMPRINT Project (2013)](warmerdam.jpg) ](../edit.php#09/dots5.frag)
In questo capitolo applicheremo ciò che abbiamo imparato fin ad ora e lo ripeteremo all'interno del canvas. Così come nel capitolo precedente, la nostra strategia sarà basata sulla moltiplicazione delle coordinate spaziali (tra 0.0 e 0.1), in modo che le forme che disegniamo tra i valori 0.0 e 1.0 saranno ripetute per creare una griglia.
*"The grid provides a framework within which human intuition and invention can operate and that it can subvert. Within the chaos of nature patterns provide a constrast and promise of order. From early patterns on pottery to geometric mosaics in Roman baths, people have long used grids to enhance their lives with decoration."* [*10 PRINT*, Mit Press, (2013)](http://10print.org/)
Prima ricordiamo la funzione [```fract()```](../glossary/?search=fract). Questa restituisce la parte frazionale di un numero, facendo in sostanza ```fract()``` il modulo di uno ([```mod(x,1.0)```](../glossary/?search=mod)). In altre parole, [```fract()```](../glossary/?search=fract) restituisce il numero dopo la virgola mobile. Il nostro sistema variabile di coordinate (```st```) va già da 0.0 a 1.0, quindi non ha senso fare una cosa simile a:
```glsl
void main(){
vec2 st = gl_FragCoord.xy/u_resolution;
vec3 color = vec3(0.0);
st = fract(st);
color = vec3(st,0.0);
gl_FragColor = vec4(color,1.0);
}
```
Ma se ingrandiamo il sistema di coordinate, diciamo di tre volte, otterremo tre sequenze di interpolazioni lineari tra 0-1: la prima tra 0-1, la seconda per le virgole mobili tra 1-2 e la terza per le virgole mobili tra 2-3.
<div class="codeAndCanvas" data="grid-making.frag"></div>
È arrivato il momento di disegnare qualcosa in ciascuno sottospazio, togliendo il commento alla riga 27 (Siccome stiamo moltiplicando sia in x sia in y, il rapporto di forma dello spazio non cambia e le forme saranno come previste).
Provate alcuni dei seguenti esercizi per capire meglio:
* Moltiplicate lo spazio per numeri diversi. Provate con valori con la virgola mobile e anche con valori diversi per x e y.
* Create una funzione riutilizzabile con questo trucco di piastrellatura.
* Suddividete lo spazio in 3 righe e 3 colonne. Trovate un modo di sapere in quale colonna e quale riga si trova il thread e usatelo per cambiare la forma che è mostrata. Provate a creare una griglia per il tris.
### Applicare le matrici all'interno dei motivi
Siccome ciascuna suddivisione, o cella, è una versione più piccola del sistema normalizzato di coordinate che abbiamo già usato, possiamo applicarle una trasformazione matrice per traslare, ruotare o ridimensionare lo spazio interno.
<div class="codeAndCanvas" data="checks.frag"></div>
* Pensate a modi interessanti di animare questo motivo. Considerate le animazioni di colore, forma e movimento. Fate tre animazioni diverse.
* Riproducete dei motivi più complicati componendo forme diverse.
[![](diamondtiles-long.png)](../edit.php#09/diamondtiles.frag)
* Combinate diversi livelli di motivi per comporre il vostro personale motivo di [Tartan Scozzese](https://www.google.com/search?q=scottish+patterns+fabric&tbm=isch&tbo=u&source=univ&sa=X&ei=Y1aFVfmfD9P-yQTLuYCIDA&ved=0CB4QsAQ&biw=1399&bih=799#tbm=isch&q=Scottish+Tartans+Patterns).
[ ![Vector Pattern Scottish Tartan di Kavalenkava](tartan.jpg) ](http://graphicriver.net/item/vector-pattern-scottish-tartan/6590076)
### Compensare i motivi
Immaginiamo di voler imitare un muro di mattoni. Guardando il muro, potete vedere un offset a mezzo mattone sull'asse x a file alternate. Come possiamo farlo?
![](brick.jpg)
Come primo passo dobbiamo sapere se la riga del nostro thread è un numero pari o dispari, perché possiamo usare ciò per determinare se abbiamo bisogno di compensare con un offset le x in quella fila.
____dobbiamo unire i prossimi due paragrafi____
Per determinare se il nostro thread è in una fila pari o dispari, useremo [```mod()```](../glossary/?search=mod) di ```2.0``` e poi vedremo se il risultato è inferiore a ```1.0``` o no. Osservate la formula seguente e togliete il commento alle ultime due righe.
<div class="simpleFunction" data="y = mod(x,2.0);
// y = mod(x,2.0) < 1.0 ? 0. : 1. ;
// y = step(1.0,mod(x,2.0));"></div>
Come potete vedere, usiamo un [operatore ternario](https://it.wikipedia.org/wiki/%3F:) per controllare se il [```mod()```](../glossary/?search=mod) di ```2.0``` sia al di sotto di ```1.0``` (seconda riga) o potremmo anche usare una funzione [```step()```](../glossary/?search=step) che fa la stessa operazione ma più velocemente. Perché? Nonostante sia difficile sapere come ciascuna carta grafica ottimizza e compila il codice, è sicuro assumere che questa funzione built-in sia più veloce di una non built-in. Ogni volta che potete usare una funzione built-in, fatelo!
Ora che abbiamo la formula per il numero dispari, possiamo applicare un offset alle file dispari per dare l'effetto *muro di mattoni* alla nostra piastrellatura. La riga 14 del codice seguente è dove stiamo usando la funzione per "rilevare" le file dispari e dare loro un offset di mezza unità sulle ```x```. Notate che per le file pari, il risultato della nostra funzione è ```0.0```, e moltiplicando ```0.0``` per l'offset di ```0.5```, otteniamo una compensazione di ```0.0```; sulle file dispari moltiplichiamo il risultato della nostra funzione, ```1.0```, per l'offset di ```0.5```, che sposta di ```0.5``` l'asse delle ```x``` del sistema.
Ora provate a togliere il commento alla riga 32 - questo allunga il rapporto di forma del sistema di coordinate per simulare l'aspetto di un "mattone moderno". Togliendo il commento alla riga 40 potete vedere come il sistema di coordinate appaia mappato con il rosso e il verde.
<div class="codeAndCanvas" data="bricks.frag"></div>
* Provate ad animare questo motivo spostando l'offset in base al tempo.
* Fate un'altra animazione dove le file pari si spostano a sinistra e le file dispari si spostano a destra.
* Riuscite a ripetere quest'effetto con le colonne?
* Provate a combinare un offset sugli assi delle ```x``` e delle ```y``` per ottenere qualcosa di simile a questo:
<a href="../edit.php#09/marching_dots.frag"><canvas id="custom" class="canvas" data-fragment-url="marching_dots.frag" width="520px" height="200px"></canvas></a>
## Tessere di Truchet
Ora che abbiamo imparato come dire se la nostra cella è in una fila o colonna pari o dispari. È possibile riutilizzare un singolo motivo in relazione alla sua posizione. Considerate il caso delle tessere di [Truchet Tiles](http://en.wikipedia.org/wiki/Truchet_tiles), dove un singolo motivo può essere rappresentato in quattro modi diversi:
![](truchet-00.png)
Cambiando il motivo lungo le tessere, è possibile costruire una serie infinita di motivi complessi.
![](truchet-01.png)
Osservate più da vicino la funzione ```rotateTilePattern()```, che suddivide lo spazio in quattro celle e assegna un angolo di rotazione a ciascuna di esse.
<div class="codeAndCanvas" data="truchet.frag"></div>
* Commentate, togliete il commento e duplicate le righe da 69 a 72 per comporre nuovi motivi.
* Cambiate il triangolo bianco e nero con un altro elemento, ad esempio: semicerchi, quadrati o linee ruotati.
* Codificate altri motivi dove gli elementi siano ruotati a seconda della loro posizione.
* Create un motivo che cambi altre proprietà a seconda della posizione degli elementi.
* Immaginate qualcos'altro, che non sia necessariamente un motivo, dove potete applicare i principi visti in questa sezione (es. esagrammi di I Ching).
<a href="../edit.php#09/iching-01.frag"><canvas id="custom" class="canvas" data-fragment-url="iching-01.frag" width="520px" height="200px"></canvas></a>
## Create il vostro insieme di tessere
Creare motivi procedurali è un esercizio mentale nel trovare il più piccole elemento riutilizzabile. Questa è una pratica antica; nel corso della storia abbiamo usato schemi e motivi per decorare tessuti, i fondi e i bordi di oggetti: dai motivi nell'antica Grecia al motivo reticolare cinese, il piacere della ripetizione e della variazione affascina la nostra immaginazione. Prendete del tempo per guardare i [motivi](https://www.pinterest.com/patriciogonzv/paterns/) [decorativi](https://archive.org/stream/traditionalmetho00chririch#page/130/mode/2up) e osservate come artisti e designers nel corso della loro lunga tradizione abbiano saputo navigare tra predicibilità dell'ordine e la sorpresa della variazione e del caos. Dai motivi geometrici arabi, ai bellissimi motivi delle stoffe africane, esiste un intero universo di motivi dal quale imparare.
![Franz Sales Meyer - A handbook of ornament (1920)](geometricpatters.png)
Con questo capitolo terminiamo la sezione sul disegno algoritmico. Nei prossimi capitoli impareremo a portare dell'entropia nei nostri shader e a produrre motivi generativi.

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

Loading…
Cancel
Save