merging master

pull/68/head
nicolas barradeau 8 years ago
parent c6d0a751f3
commit 82ebf1fbbe

3
.gitignore vendored

@ -1,4 +1,3 @@
/src
.DS_Store
.dropbox
tmp.md
@ -8,4 +7,4 @@ book.pdf
log/*
/.idea
.idea/
idea/
idea/

@ -2,7 +2,7 @@
<canvas id="custom" class="canvas" data-fragment-url="cmyk-halftone.frag" data-textures="vangogh.jpg" width="700px" height="320px"></canvas>
les images ci-dessus onté été crées de différentes manières.
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.

@ -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](http://thebookofshaders.com/appendix/)
- [Eseguire gli esempi su un Raspberry Pi senza navigatore](http://thebookofshaders.com/appendix/)
- [Fare un PDF del libro da stampare](http://thebookofshaders.com/appendix/)
- Utilizzare la [repository on-line](https://github.com/patriciogonzalezvivo/thebookofshaders) per aiutare a risolvere i problemi e per condividere il codice.

@ -1,7 +1,7 @@
# bien démarrer
## qu'est-ce qu'un fragment shader?
Au chapitre précédent, nous avons décrit les shaders comme l'équivalent l'avènement de la presse de Gutenberg pour l'impression. Pourquoi cette comparaison mais surtout: Qu'est-ce qu'un 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)
@ -81,4 +81,4 @@ Mais n'ayez crainte! au cours des chapitres suivants, nous abordons les problèm
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!
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!

@ -36,7 +36,7 @@ on peut spécifier la précision de chaque variable se servant des Float, ligne
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 à 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.
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:

@ -23,7 +23,7 @@ Les noms peuvent varier selon les implémentations et les plateformes mais dans
```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/) utilises les mêmes uniforms avec les noms suivants:
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)
@ -42,11 +42,11 @@ la valeur *absolue* d'une fonction de sinus sera quant à elle toujours comprise
<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émenent parfois l'accélération *matérielle* de certaines opérations, certaines fonctions trigonométriques telles que:
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.
Eassayons de jouer avec le code ci dessus.
Essayons de jouer avec le code ci dessus.
* Ralentissez la fréquence jusqu'à ce que le changement de couleur deviennent imperceptible.
@ -75,7 +75,7 @@ Dans le code ci-dessus, nous *normalisons* les coordonnées du *fragment* en les
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'ets comme de fabriquer un tout petit bateau dans une bouteille, c'est dur, c'est beau et c'est gratifiant.
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)
@ -92,4 +92,4 @@ Voyons ce que nous avez appris et compris du code.
* 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.
Au chapitre suivant, nous verrons comment fabriquer nos propres outils dans THREE.js, Processing et OpenFrameworks.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

@ -1,8 +1,8 @@
## Colors
![Paul Klee - Color Chart (1931)](klee.jpg)
We haven't had 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.
## 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```.
@ -217,6 +217,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" 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.
@ -225,9 +229,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.

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

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 240 KiB

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 139 KiB

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 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.

Before

Width:  |  Height:  |  Size: 581 KiB

After

Width:  |  Height:  |  Size: 581 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

After

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 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: 42 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 KiB

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 KiB

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 338 KiB

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 104 KiB

@ -1,38 +0,0 @@
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
float hash(vec2 st) {
float h = dot(st,vec2(127.1,311.7));
return -1.0 + 2.0*fract(sin(h)*43758.5453123);
}
// Gradient Noise by Inigo Quilez - iq/2013
// https://www.shadertoy.com/view/XdXGW8
float noise(vec2 st) {
vec2 i = floor(st);
vec2 f = fract(st);
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( hash( i + vec2(0.0,0.0) ),
hash( i + vec2(1.0,0.0) ), u.x),
mix( hash( i + vec2(0.0,1.0) ),
hash( i + vec2(1.0,1.0) ), u.x), u.y);
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
vec2 pos = vec2(st*10.0);
color = vec3(noise(pos)*.5+.5);
gl_FragColor = vec4(color,1.0);
}

@ -1,75 +0,0 @@
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
vec2 random2( vec2 p ) {
return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453);
}
#define ANIMATE
vec3 voronoi( in vec2 x, float rnd ) {
vec2 n = floor(x);
vec2 f = fract(x);
// first pass: regular voronoi
vec2 mg = vec2(0.0);
vec2 mr = vec2(0.0);
float md = 8.0;
for (int j=-1; j<=1; j++ ) {
for (int i=-1; i<=1; i++ ) {
vec2 g = vec2(float(i),float(j));
vec2 o = random2( n + g )*rnd;
#ifdef ANIMATE
o = 0.5 + 0.5*sin( u_time + 6.2831*o );
#endif
vec2 r = g + o - f;
float d = dot(r,r);
if( d<md ) {
md = d;
mr = r;
mg = g;
}
}
}
return vec3( md, mr );
// // second pass: distance to borders
// md = 8.0;
// for (int j=-2; j<=2; j++ ) {
// for (int i=-2; i<=2; i++ ) {
// vec2 g = mg + vec2(float(i),float(j));
// vec2 o = random2(n + g)*rnd;
// #ifdef ANIMATE
// o = 0.5 + 0.5*sin( u_time + 6.2831*o );
// #endif
// vec2 r = g + o - f;
// if( dot(mr-r,mr-r)>0.00001 )
// md = min( md, dot( 0.5*(mr+r), normalize(r-mr) ) );
// }
// }
// return vec3( md, mr );
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(0.0);
float d = dot(st-.5,st-.5);
vec3 c = voronoi( 10.*st, 1.);//pow(d,.4) );
// isolines
color = c.x*(0.5 + 0.5*sin(64.0*c.x))*vec3(1.0);
// borders
color = mix( vec3(1.0), color, smoothstep( 0.01, 0.02, c.x ) );
// feature points
// float dd = length( c.yz );
// color += vec3(1.)*(1.0-smoothstep( 0.0, 0.1, dd));
gl_FragColor = vec4(color,1.0);
}

@ -1,10 +0,0 @@
http://github.prideout.net/coordinate-fields/
https://briansharpe.wordpress.com/2011/12/01/optimized-artifact-free-gpu-cellular-noise/
http://www.rhythmiccanvas.com/research/papers/worley.pdf
http://webstaff.itn.liu.se/~stegu/GLSL-cellular/GLSL-cellular-notes.pdf
http://www.iquilezles.org/www/articles/voronoise/voronoise.htm
http://www.iquilezles.org/www/articles/smoothvoronoi/smoothvoronoi.htm
http://www.iquilezles.org/www/articles/voronoilines/voronoilines.htm

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

@ -1,4 +1,5 @@
// Author @patriciogv - 2015
// Author: Stefan Gustavson
// Title: Worley noise 2x2
#ifdef GL_ES
precision mediump float;
@ -24,9 +25,9 @@ vec4 permute(vec4 x) {
// If you need a smooth F2, use the slower 3x3 version.
// F1 is sometimes wrong, too, but OK for most purposes.
vec2 cellular2x2(vec2 P) {
#define K 0.142857142857 // 1/7
#define K2 0.0714285714285 // K/2
#define jitter 0.8 // jitter 1.0 makes F1 wrong more often
#define K 0.142857142857 // 1/7
#define K2 0.0714285714285 // K/2
#define jitter 0.8 // jitter 1.0 makes F1 wrong more often
vec2 Pi = mod(floor(P), 289.0);
vec2 Pf = fract(P);
vec4 Pfx = Pf.x + vec4(-0.5, -1.5, -0.5, -1.5);
@ -58,7 +59,7 @@ vec2 cellular2x2(vec2 P) {
void main(void) {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec2 F = cellular2x2(st*20.);
vec2 F = cellular2x2(st*20.+vec2(u_time,0.));
float n = 1.0-1.5*F.x;
gl_FragColor = vec4(n, n, n, 1.0);

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 KiB

@ -1,3 +1,6 @@
// Author: Stefan Gustavson
// Title: Worley noise 2x2x2
#ifdef GL_ES
precision mediump float;
#endif
@ -24,12 +27,12 @@ vec3 permute(vec3 x) {
// F2 is often wrong and has sharp discontinuities.
// If you need a good F2, use the slower 3x3x3 version.
vec2 cellular2x2x2(vec3 P) {
#define K 0.142857142857 // 1/7
#define Ko 0.428571428571 // 1/2-K/2
#define K2 0.020408163265306 // 1/(7*7)
#define Kz 0.166666666667 // 1/6
#define Kzo 0.416666666667 // 1/2-1/6*2
#define jitter 0.8 // smaller jitter gives less errors in F2
#define K 0.142857142857 // 1/7
#define Ko 0.428571428571 // 1/2-K/2
#define K2 0.020408163265306 // 1/(7*7)
#define Kz 0.166666666667 // 1/6
#define Kzo 0.416666666667 // 1/2-1/6*2
#define jitter 0.8 // smaller jitter gives less errors in F2
vec3 Pi = mod(floor(P), 289.0);
vec3 Pf = fract(P);
vec4 Pfx = Pf.x + vec4(0.0, -1.0, 0.0, -1.0);

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

@ -1,4 +1,5 @@
// Author @patriciogv - 2015
// Author: Stefan Gustavson
// Title: Classic 2D cellular noise
#ifdef GL_ES
precision mediump float;
@ -15,9 +16,9 @@ vec3 permute(vec3 x) {
// Cellular noise, returning F1 and F2 in a vec2.
// Standard 3x3 search window for good F1 and F2 values
vec2 cellular(vec2 P) {
#define K 0.142857142857 // 1/7
#define Ko 0.428571428571 // 3/7
#define jitter 1.0 // Less gives more regular pattern
#define K 0.142857142857 // 1/7
#define Ko 0.428571428571 // 3/7
#define jitter 1.0 // Less gives more regular pattern
vec2 Pi = mod(floor(P), 289.0);
vec2 Pf = fract(P);
vec3 oi = vec3(-1.0, 0.0, 1.0);
@ -58,7 +59,7 @@ vec2 cellular(vec2 P) {
void main(void) {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st *= 10.;
vec2 F = cellular(st);
vec2 F = cellular(st+vec2(u_time,0.));
float facets = 0.1+(F.y-F.x);
float dots = smoothstep(0.05, 0.1, F.x);
float n = facets * dots;

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 KiB

@ -14,7 +14,6 @@ vec2 random2( vec2 p ) {
return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453);
}
#define ANIMATE
vec3 voronoi( in vec2 x ) {
vec2 n = floor(x);
vec2 f = fract(x);
@ -22,13 +21,12 @@ vec3 voronoi( in vec2 x ) {
// first pass: regular voronoi
vec2 mg, mr;
float md = 8.0;
for (int j=-1; j<=1; j++ ) {
for (int i=-1; i<=1; i++ ) {
for (int j= -1; j <= 1; j++) {
for (int i= -1; i <= 1; i++) {
vec2 g = vec2(float(i),float(j));
vec2 o = random2( n + g );
#ifdef ANIMATE
o = 0.5 + 0.5*sin( u_time + 6.2831*o );
#endif
vec2 r = g + o - f;
float d = dot(r,r);
@ -42,27 +40,30 @@ vec3 voronoi( in vec2 x ) {
// second pass: distance to borders
md = 8.0;
for (int j=-2; j<=2; j++ ) {
for (int i=-2; i<=2; i++ ) {
for (int j= -2; j <= 2; j++) {
for (int i= -2; i <= 2; i++) {
vec2 g = mg + vec2(float(i),float(j));
vec2 o = random2( n + g );
#ifdef ANIMATE
o = 0.5 + 0.5*sin( u_time + 6.2831*o );
#endif
vec2 r = g + o - f;
if( dot(mr-r,mr-r)>0.00001 )
md = min( md, dot( 0.5*(mr+r), normalize(r-mr) ) );
if ( dot(mr-r,mr-r)>0.00001 ) {
md = min(md, dot( 0.5*(mr+r), normalize(r-mr) ));
}
}
}
return vec3( md, mr );
return vec3(md, mr);
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
vec3 color = vec3(0.0);
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.);
vec3 c = voronoi( 8.0*st );
// Scale
st *= 3.;
vec3 c = voronoi(st);
// isolines
color = c.x*(0.5 + 0.5*sin(64.0*c.x))*vec3(1.0);

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 KiB

@ -41,9 +41,11 @@ float iqnoise( in vec2 x, float u, float v ) {
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(0.0);
float n = iqnoise( 30.0*st, abs(cos(u_time*.25)), 0.);
st *= 10.;
float n = iqnoise(st, u_mouse.x/u_resolution.x, u_mouse.y/u_resolution.y);
gl_FragColor = vec4(vec3(n),1.0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

@ -1,5 +1,5 @@
// Author @patriciogv - 2015
// http://patriciogonzalezvivo.com
// Author: Stefan Gustavson
// Title: Classic 3D cellular noise
#ifdef GL_ES
precision mediump float;
@ -27,12 +27,12 @@ vec3 permute(vec3 x) {
// implementation of Worley noise hands down.
vec2 cellular(vec3 P) {
#define K 0.142857142857 // 1/7
#define Ko 0.428571428571 // 1/2-K/2
#define K2 0.020408163265306 // 1/(7*7)
#define Kz 0.166666666667 // 1/6
#define Kzo 0.416666666667 // 1/2-1/6*2
#define jitter 1.0 // smaller jitter gives more regular pattern
#define K 0.142857142857 // 1/7
#define Ko 0.428571428571 // 1/2-K/2
#define K2 0.020408163265306 // 1/(7*7)
#define Kz 0.166666666667 // 1/6
#define Kzo 0.416666666667 // 1/2-1/6*2
#define jitter 1.0 // smaller jitter gives more regular pattern
vec3 Pi = mod(floor(P), 289.0);
vec3 Pf = fract(P) - 0.5;
@ -188,6 +188,9 @@ void main(void) {
st *= 10.;
vec2 F = cellular(vec3(st,u_time));
float dots = smoothstep(0.05, 0.1, F.x);
float n = F.y-F.x;
n *= dots;
gl_FragColor = vec4(n, n, n, 1.0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 559 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 804 KiB

@ -1,93 +1,178 @@
## Emergin patterns
![](dragonfly.jpg)
We made pseudo random values from a sine wave, then from it we construct noise. We went from the absolute chaos to smooth random variations we can control.
With it we were able to suggest more organic visual gestures. But we still far away from the “real” thing. If we look to satelites images, coherent structers emerge from mountans formation, looking closely to the surface of a leave we will see a clear an inner pattern. This surfaces speaks about the forces involve on their creation. On the tension of the laws applied apply to them together with the forces of their surrandings.
The next step in our quest on learning how to mimic nature will be to learn about iterations. More precisely iterations on time and iterations on space.
## Cellular Noise
### Fractal Brownian Motion
In 1996, sixteen years after Perlin's Noise and five years before his Simplex Noise, [Steven Worley wrote a paper call “A Cellular Texture Basis Function”](http://www.rhythmiccanvas.com/research/papers/worley.pdf). In it he describes a procedural texturing technique now extensively use by the graphics community.
Noise tends to means different things for different people. Musicians will think it in disturbing sounds, communicators as interference and astrophysics as cosmic microwave background. In fact most of this concept have one things in common that bring as back to the begining of random. Waves and their properties. Audio or electromagnetical waves, fluctuation overtime of a signal. That change happens in amplitud and frequency. The ecuation for it looks like this:
To understand the principles behind it we need to start thinking in terms iterations.
<div class="simpleFunction" data="
float amplitud = 1.;
float frequency = 1.;
y = amplitud * sin(x * frequency);
"></div>
### A distance field for some points
* Try changing the values of the frequency and amplitud to understand how they behave.
* Using shaping functions try changing the amplitud overtime.
* Using shaping function try changing the frequency overtime.
Let's say we want to make a distance field of 4 points. What we need to do? in a nutshell, **for each pixel we want to calculate the distance to the closest point**. That means that we need to iterate through all the points and store the value to the most close one.
By doing the last to excersize you have manage to "modulate" a sine wave, and you just create AM (amplitud modulated) and FM (frequency modulated) waves. Congratulations!
Another interesting property of waves is their ability to add up. Add the following lines to the previus example and pay atention how the frequencies and amplitudes change conform we add different waves.
![](cell-00.png)
```glsl
float t = 0.01*(-u_time*130.0);
y += sin(x*2.1 + t)*4.5;
y += sin(x*1.72 + t*1.121)*4.0;
y += sin(x*2.221 + t*0.437)*5.0;
y += sin(x*3.1122+ t*4.269)*2.5;
y *= 0.06;
float m_dist = 1.; // minimun distance
for (int i = 0; i < TOTAL_POINTS; i++) {
float dist = distance(st, points[i]);
m_dist = min(m_dist, dist);
}
```
* Experiment by changing their values.
* Is it possible to cancel two waves? how that will look like?
* Is it possible to add waves in such a way that they will amplify each other?
To do that we can use a ```for``` loop to iterate through an array of points and keep track of the minimum distance using a [```min()```](../glossary/?search=min) function. Here a brief implementation of that:
<div class="codeAndCanvas" data="cellnoise-00.frag"></div>
Note in the above code, how one of the points is the mouse position. Play with it so you can get a more intuitive idea of how this code behaves. Then try this:
- How can you animate the rest of the points?
- After reading [the chapter about shapes](../07/), imagine interesting ways to use this distance field?
- What if you want to add more points to this distance field? What if we want to dynamically add/subtract points?
### Tiling and iterating
You probably notice that ```for``` loops and *arrays* are not so friendly in GLSL. Loops don't accept dynamic limits on their condition. Also iterating through a lot of instances reduce the performance of your shader significantly. So... We need to find another strategy.
In music, each note is asociated with specific a frequency. This frequencies seams to respond to a pattern where it self in what we call scale.
![](cell-01.png)
By adding different iterations of noise (*octaves*), where in each one increment the frequencies (*Lacunarity*) and decreasing amplitude (*gain*) of the **noise** we can obtain a bigger level of granularity on the noise. This technique is call Fractal Brownian Motion (*fBM*) and in it simplest form looks like the following code
One way to approach this problem is to divide the space in tiles. Not every pixel need to check every single points, right? They just need to check the points that are close to them. That's the main idea of [Steven Worley's paper](http://www.rhythmiccanvas.com/research/papers/worley.pdf). We already subdivide the space into cells in the chapters about: [patterns](../09/), [random](../10/) and [noise](../11/). Hopefully by now you are familiarize with this technique.
<div class="simpleFunction" data="// Properties
const int octaves = 1;
float lacunarity = 2.0;
float gain = 0.5;
//
// Initial values
float amplitud = 0.5;
float frequency = x;
//
// Loop of octaves
for (int i = 0; i < octaves; i++) {
&#9;y += amplitud * noise(frequency);
&#9;frequency *= lacunarity;
&#9;amplitud *= gain;
}"></div>
```glsl
// Scale
st *= 3.;
// Tile the space
vec2 i_st = floor(st);
vec2 f_st = fract(st);
```
So what's the plan? We will use the tile coordinates (stored in the integer coordinate, ```i_st```) to construct a random position of a point. The ```random2f``` function we will use receive a ```vec2``` and give us a ```vec2``` with a random position. So for each tile we will have one point in a random position.
* Progressively change the number of octaves to iterate from 1 to 2, 4, 8 and 10. See want happens.
* With over 4 octaves try changing the lacunarity value.
* Also with over 4 octaves change the gain value and see what happens.
```glsl
vec2 point = random2(i_st);
```
Note how each in each octave the noise seams to have more detail. Also note the self similarity while more octaves are added.
Each pixel inside that tile (stored in the float coordinate, ```f_st```) will check their distance to that random point.
The following code is an example of how fBm could be implemented on two dimensions.
```glsl
vec2 diff = point - f_st;
float dist = length(diff);
```
<div class='codeAndCanvas' data='2d-fbm.frag'></div>
This will look like this:
* Reduce the numbers of octaves by changing the value on line 37
* Modify the lacunarity of the fBm on line 47
* Explore by changing the gain on line 48
<a href="../edit.html#12/cellnoise-01.frag"><img src="cellnoise.png" width="520px" height="200px"></img></a>
This techniques is use commonly to construct procedural landscapes. The self similarity of the fBm is perfect for mountains, together with a close cassing known as turbulence. Esentially a fBm but constructed from the absolute value of a signed noise.
We still need to calculate the points around each pixel. Not just the one in the current tile. For that we need to **iterate** through the neighbor tiles. Not all of them. just the one immediately around it. That means from ```-1``` (left) to ```1``` (right) tile in ```x``` axis and ```-1``` (bottom) to ```1``` (top) in ```y``` axis. A 3x3 kernel of 9 tiles that we can iterate using a double ```for``` loop like this one:
```glsl
for (int i = 0; i < OCTAVES; i++) {
value += amplitud * abs(snoise(st));
st *= 2.;
amplitud *= .5;
for (int y= -1; y <= 1; y++) {
for (int x= -1; x <= 1; x++) {
// Neighbor place in the grid
vec2 neighbor = vec2(float(x),float(y));
...
}
}
```
<a href="../edit.html#12/turbulence.frag"><canvas id="custom" class="canvas" data-fragment-url="turbulence.frag" width="520px" height="200px"></canvas></a>
![](cell-02.png)
Now, we can predict the position of the points on each one of the neighbors in our double ```for``` loop by adding the neighbor tile offset to the current tile coordinate.
```glsl
...
// Random position from current + neighbor place in the grid
vec2 point = random2(i_st + neighbor);
...
```
The rest is all about calculating the distance to that point and store the closest one in a variable call ```m_dist``` (for minimal distance).
```glsl
...
vec2 diff = neighbor + point - f_st;
// Distance to the point
float dist = length(diff);
// Keep the closer distance
m_dist = min(m_dist, dist);
...
```
The above code is inspired by [this Inigo's Quilez article](http://www.iquilezles.org/www/articles/smoothvoronoi/smoothvoronoi.htm) where he said:
*"... it might be worth noting that there's a nice trick in this code above. Most implementations out there suffer from precision issues, because they generate their random points in "domain" space (like "world" or "object" space), which can be arbitrarily far from the origin. One can solve the issue moving all the code to higher precision data types, or by being a bit clever. My implementation does not generate the points in "domain" space, but in "cell" space: once the integer and fractional parts of the shading point are extracted and therefore the cell in which we are working identified, all we care about is what happens around this cell, meaning we can drop all the integer part of our coordinates away all together, saving many precision bits. In fact, in a regular voronoi implementation the integer parts of the point coordinates simply cancel out when the random per cell feature points are subtracted from the shading point. In the implementation above, we don't even let that cancelation happen, cause we are moving all the computations to "cell" space. This trick also allows one to handle the case where you want to voronoi-shade a whole planet - one could simply replace the input to be double precision, perform the floor() and fract() computations, and go floating point with the rest of the computations without paying the cost of changing the whole implementation to double precision. Of course, same trick applies to Perlin Noise patterns (but i've never seen it implemented nor documented anywhere)."*
Recaping: we subdivide the space in tiles; each pixel will calculate the distance to the point in their own tile and the other 8 tiles; store the closest distance. The resultant is distance field that looks like the following example:
Another member of this family is the ridge. Constructed similarly to the turbolence but with some extra calculations:
<div class="codeAndCanvas" data="cellnoise-02.frag"></div>
Explore by:
- Scaling the space by different values.
- Can you think in other ways to animate the points?
- What if we want to compute an extra point with the mouse position?
- What other ways of constructing this distance field beside ```m_dist = min(m_dist, dist);```, can you imagine?
- What interesting patterns you can make with this distance field?
This algorithm can also be interpreted from the perspective of the points and not the pixels. In that case it can be describe as: each point grows until it finds the area of another point. Which mirrors some of the grow rules on nature. Living forms are shaped by this tension between an inner force to expand and grow limited by the forces
on their medium. The classic algorithm that simulate this behavior is named after [Georgy Voronoi](https://en.wikipedia.org/wiki/Georgy_Voronoy).
![](monokot_root.jpg)
### Voronoi Algorithm
Constructing voronoi diagrams from cellular noise is less hard that what it seams. We just need to *keep* some extra information about the precise point which is closer to the pixel. For that we are going to use a ```vec2``` call ```m_point```. By storing the position to the center of the closest point will be "keeping" and "unique" identifier of that point.
```glsl
n = abs(n); // create creases
n = offset - n; // invert so creases are at top
n = n * n; // sharpen creases
...
if( dist < m_dist ) {
m_dist = dist;
m_point = point;
}
...
```
<a href="../edit.html#12/ridge.frag"><canvas id="custom" class="canvas" data-fragment-url="ridge.frag" width="520px" height="200px"></canvas></a>
Note in the following code that we are not longer using ```min``` to calculate the closest distance but a regular ```if``` statement. Why? Because we actually want to do something every time a new closer point appears, store it position (lines 32 to 37).
<div class="codeAndCanvas" data="vorono-00.frag"></div>
Note how the color of the moving cell (hook to the mouse position) change color according it position. That's because the color is assigned using the value (position) of the closes point.
Like we did before now is time to scale this up, switching to [Steven Worley's paper approach](http://www.rhythmiccanvas.com/research/papers/worley.pdf). Try implementing it your self. You can use the help of the following example by clicking on it.
<a href="../edit.html#12/vorono-01.frag"><canvas id="custom" class="canvas" data-fragment-url="vorono-01.frag" width="520px" height="200px"></canvas></a>
Once you figurate out this algorithm think interesting and creative uses for it.
![Extended Voronoi - Leo Solaas (2011)](solas.png)
![Cloud Cities - Tomás Saraceno (2011)](saraceno.jpg)
![Accretion Disc Series - Clint Fulkerson](accretion.jpg)
![Vonoroi Puzzle - Reza Ali (2015)](reza.png)
### Improving Voronoi
In 2011, [Stefan Gustavson optimized Steven Worley's algorithm to GPU](http://webstaff.itn.liu.se/~stegu/GLSL-cellular/GLSL-cellular-notes.pdf) by only iterating trough a 2x2 matrix instead of 3x3. This reduce the work significantly but can create artifacts in form of discontinuities. Take a look to the following examples.
<div class="glslGallery" data="12/2d-cnoise-2x2,12/2d-cnoise-2x2x2,12/2d-cnoise,12/3d-cnoise" data-properties="clickRun:edior,openFrameIcon:false"></div>
Later in 2012 [Inigo Quilez wrote an article on how to make precise voronoi borders](http://www.iquilezles.org/www/articles/voronoilines/voronoilines.htm).
<a href="../edit.html#12/2d-voronoi.frag"><img src="2d-voronoi.gif" width="520px" height="200px"></img></a>
Inigio's experiment on voronoi didn't stop there. In 2014 he wrote this nice article about what he call [voro-noise](http://www.iquilezles.org/www/articles/voronoise/voronoise.htm), and exploration between regular noise and voronoi. In his words:
*"Despite this similarity, the fact is that the way the grid is used in both patterns is different. Noise interpolates/averages random values (as in value noise) or gradients (as in gradient noise), while Voronoi computes the distance to the closest feature point. Now, smooth-bilinear interpolation and minimum evaluation are two very different operations, or... are they? Can they perhaps be combined in a more general metric? If that was so, then both Noise and Voronoi patterns could be seen as particular cases of a more general grid-based pattern generator?"*
<a href="../edit.html#12/2d-voronoise.frag"><canvas id="custom" class="canvas" data-fragment-url="2d-voronoise.frag" width="520px" height="200px"></canvas></a>
Now is up to look closely at things, be inspired by nature to find your own voice on this technique.
![Deyrolle glass film - 1831](DeyrolleFilm.png)
<div class="glslGallery" data="12/metaballs,12/stippling,12/cell,12/tissue,12/cracks,160504143842" data-properties="clickRun:edior,openFrameIcon:false"></div>

@ -0,0 +1 @@
Cellular Noise

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

@ -1,4 +1,5 @@
// Author @patriciogv - 2015
// Author: @patriciogv - 2015
// Title: Cell
#ifdef GL_ES
precision mediump float;
@ -45,6 +46,15 @@ vec2 cellular2x2(vec2 P) {
void main(void) {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st = (st-.5)*1.+.5;
if (u_resolution.y > u_resolution.x ) {
st.y *= u_resolution.y/u_resolution.x;
st.y -= (u_resolution.y*.5-u_resolution.x*.5)/u_resolution.x;
} else {
st.x *= u_resolution.x/u_resolution.y;
st.x -= (u_resolution.x*.5-u_resolution.y*.5)/u_resolution.y;
}
st -= .5;
st *= .7;
vec2 F = cellular2x2(st*40.*(.1+1.0-dot(st,st)*5.));
@ -52,6 +62,6 @@ void main(void) {
float facets = 0.1+(F.y-F.x);
float dots = smoothstep(0.05, 0.1, F.x);
float n = facets * dots;
n = 1.-step(.2,facets)*dots;
n = step(.2,facets)*dots;
gl_FragColor = vec4(n, n, n, 1.0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

@ -0,0 +1,43 @@
// Author: @patriciogv
// Title: 4 cells DF
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(.0);
// Cell positions
vec2 point[5];
point[0] = vec2(0.83,0.75);
point[1] = vec2(0.60,0.07);
point[2] = vec2(0.28,0.64);
point[3] = vec2(0.31,0.26);
point[4] = u_mouse/u_resolution;
float m_dist = 1.; // minimun distance
// Iterate through the points positions
for (int i = 0; i < 5; i++) {
float dist = distance(st, point[i]);
// Keep the closer distance
m_dist = min(m_dist, dist);
}
// Draw the min distance (distance field)
color += m_dist;
// Show isolines
// color -= step(.7,abs(sin(50.0*m_dist)))*.3;
gl_FragColor = vec4(color,1.0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

@ -0,0 +1,46 @@
// Author: @patriciogv
// Title: CellularNoise
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
vec2 random2( vec2 p ) {
return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453);
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(.0);
// Scale
st *= 3.;
// Tile the space
vec2 i_st = floor(st);
vec2 f_st = fract(st);
vec2 point = random2(i_st);
vec2 diff = point - f_st;
float dist = length(diff);
// Draw the min distance (distance field)
color += dist;
// Draw cell center
color += 1.-step(.02, dist);
// Draw grid
color.r += step(.98, f_st.x) + step(.98, f_st.y);
// Show isolines
// color -= step(.7,abs(sin(27.0*dist)))*.5;
gl_FragColor = vec4(color,1.0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

@ -0,0 +1,65 @@
// Author: @patriciogv
// Title: CellularNoise
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
vec2 random2( vec2 p ) {
return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453);
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(.0);
// Scale
st *= 3.;
// Tile the space
vec2 i_st = floor(st);
vec2 f_st = fract(st);
float m_dist = 1.; // minimun distance
for (int y= -1; y <= 1; y++) {
for (int x= -1; x <= 1; x++) {
// Neighbor place in the grid
vec2 neighbor = vec2(float(x),float(y));
// Random position from current + neighbor place in the grid
vec2 point = random2(i_st + neighbor);
// Animate the point
point = 0.5 + 0.5*sin(u_time + 6.2831*point);
// Vector between the pixel and the point
vec2 diff = neighbor + point - f_st;
// Distance to the point
float dist = length(diff);
// Keep the closer distance
m_dist = min(m_dist, dist);
}
}
// Draw the min distance (distance field)
color += m_dist;
// Draw cell center
color += 1.-step(.02, m_dist);
// Draw grid
color.r += step(.98, f_st.x) + step(.98, f_st.y);
// Show isolines
// color -= step(.7,abs(sin(27.0*m_dist)))*.5;
gl_FragColor = vec4(color,1.0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 812 KiB

@ -1,4 +1,5 @@
// Author @patriciogv - 2015
// Author: @patriciogv - 2015
// Title: Cracks
#ifdef GL_ES
precision mediump float;
@ -57,6 +58,14 @@ vec2 cellular2x2(vec2 P) {
void main(void) {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st = (st-.5)*.75+.5;
if (u_resolution.y > u_resolution.x ) {
st.y *= u_resolution.y/u_resolution.x;
st.y -= (u_resolution.y*.5-u_resolution.x*.5)/u_resolution.x;
} else {
st.x *= u_resolution.x/u_resolution.y;
st.x -= (u_resolution.x*.5-u_resolution.y*.5)/u_resolution.y;
}
vec2 F = cellular2x2(st*20.);

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

@ -1,7 +1,7 @@
<?php
$path = "..";
$subtitle = ": Fractal Brownian Motion";
$subtitle = ": More noise";
$README = "README";
$language = "";

@ -0,0 +1,55 @@
// Author: @patriciogv - 2015
// Title: Metaballs
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
vec2 random2( vec2 p ) {
return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453);
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(.0);
// Scale
st *= 5.;
// Tile the space
vec2 i_st = floor(st);
vec2 f_st = fract(st);
float m_dist = 1.; // minimun distance
for (int j= -1; j <= 1; j++ ) {
for (int i= -1; i <= 1; i++ ) {
// Neighbor place in the grid
vec2 neighbor = vec2(float(i),float(j));
// Random position from current + neighbor place in the grid
vec2 offset = random2(i_st + neighbor);
// Animate the offset
offset = 0.5 + 0.5*sin(u_time + 6.2831*offset);
// Position of the cell
vec2 pos = neighbor + offset - f_st;
// Cell distance
float dist = length(pos);
// Metaball it!
m_dist = min(m_dist, m_dist*dist);
}
}
// Draw cells
color += step(0.060, m_dist);
gl_FragColor = vec4(color,1.0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 556 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 608 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 KiB

@ -1,4 +1,5 @@
// Author @patriciogv - 2015
// Author: @patriciogv - 2015
// Title: Stippling
#ifdef GL_ES
precision mediump float;
@ -57,6 +58,14 @@ vec2 cellular2x2(vec2 P) {
void main(void) {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st = (st-.5)*.75+.5;
if (u_resolution.y > u_resolution.x ) {
st.y *= u_resolution.y/u_resolution.x;
st.y -= (u_resolution.y*.5-u_resolution.x*.5)/u_resolution.x;
} else {
st.x *= u_resolution.x/u_resolution.y;
st.x -= (u_resolution.x*.5-u_resolution.y*.5)/u_resolution.y;
}
vec2 F = cellular2x2(st*20.);

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

@ -1,3 +1,6 @@
// Author: @patriciogv - 2015
// Title: Tissue
#ifdef GL_ES
precision mediump float;
#endif
@ -60,13 +63,19 @@ vec3 voronoi( in vec2 x, float rnd ) {
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st = (st-.5)*.75+.5;
if (u_resolution.y > u_resolution.x ) {
st.y *= u_resolution.y/u_resolution.x;
st.y -= (u_resolution.y*.5-u_resolution.x*.5)/u_resolution.x;
} else {
st.x *= u_resolution.x/u_resolution.y;
st.x -= (u_resolution.x*.5-u_resolution.y*.5)/u_resolution.y;
}
vec3 color = vec3(0.0);
float d = dot(st-.5,st-.5);
vec3 c = voronoi( 20.*st, pow(d,.4) );
// isolines
// color = c.x*(0.5 + 0.5*sin(64.0*c.x))*vec3(1.0);
// borders
color = mix( vec3(1.0), color, smoothstep( 0.01, 0.02, c.x ) );
// feature points

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

@ -0,0 +1,54 @@
// Author: @patriciogv
// Title: 4 cells voronoi
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(.0);
// Cell positions
vec2 point[5];
point[0] = vec2(0.83,0.75);
point[1] = vec2(0.60,0.07);
point[2] = vec2(0.28,0.64);
point[3] = vec2(0.31,0.26);
point[4] = u_mouse/u_resolution;
float m_dist = 1.; // minimun distance
vec2 m_point; // minimum position
// Iterate through the points positions
for (int i = 0; i < 5; i++) {
float dist = distance(st, point[i]);
if ( dist < m_dist ) {
// Keep the closer distance
m_dist = dist;
// Kepp the position of the closer point
m_point = point[i];
}
}
// Add distance field to closest point center
color += m_dist*2.;
// tint acording the closest point position
color.rg = m_point;
// Show isolines
color -= abs(sin(80.0*m_dist))*0.07;
// Draw point center
color += 1.-step(.02, m_dist);
gl_FragColor = vec4(color,1.0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 955 KiB

@ -0,0 +1,62 @@
// Author: @patriciogv
// Title: Simple Voronoi
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
vec2 random2( vec2 p ) {
return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453);
}
void main() {
vec2 st = gl_FragCoord.xy/u_resolution.xy;
st.x *= u_resolution.x/u_resolution.y;
vec3 color = vec3(.0);
// Scale
st *= 5.;
// Tile the space
vec2 i_st = floor(st);
vec2 f_st = fract(st);
float m_dist = 10.; // minimun distance
vec2 m_point; // minimum point
for (int j=-1; j<=1; j++ ) {
for (int i=-1; i<=1; i++ ) {
vec2 neighbor = vec2(float(i),float(j));
vec2 point = random2(i_st + neighbor);
point = 0.5 + 0.5*sin(u_time + 6.2831*point);
vec2 diff = neighbor + point - f_st;
float dist = length(diff);
if( dist < m_dist ) {
m_dist = dist;
m_point = point;
}
}
}
// Assign a color using the closest point position
color += dot(m_point,vec2(.3,.6));
// Add distance field to closest point center
// color.g = m_dist;
// Show isolines
color -= abs(sin(40.0*m_dist))*0.07;
// Draw cell center
color += 1.-step(.05, m_dist);
// Draw grid
color.r += step(.98, f_st.x) + step(.98, f_st.y);
gl_FragColor = vec4(color,1.0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Before

Width:  |  Height:  |  Size: 370 KiB

After

Width:  |  Height:  |  Size: 370 KiB

@ -1,27 +1,105 @@
## Fractals
![Due East over Shadequarter Mountain - Matthew Rangel (2005) ](rangel.jpg)
https://www.shadertoy.com/view/lsX3W4
## Fractal Brownian Motion
https://www.shadertoy.com/view/Mss3Wf
Noise tends to means different things for different people. Musicians will think it in disturbing sounds, communicators as interference and astrophysics as cosmic microwave background. In fact most of this concept have one things in common that bring as back to the begining of random. Waves and their properties. Audio or electromagnetical waves, fluctuation overtime of a signal. That change happens in amplitud and frequency. The ecuation for it looks like this:
https://www.shadertoy.com/view/4df3Rn
<div class="simpleFunction" data="
float amplitud = 1.;
float frequency = 1.;
y = amplitud * sin(x * frequency);
"></div>
https://www.shadertoy.com/view/Mss3R8
* Try changing the values of the frequency and amplitud to understand how they behave.
* Using shaping functions try changing the amplitud overtime.
* Using shaping function try changing the frequency overtime.
https://www.shadertoy.com/view/4dfGRn
By doing the last to excersize you have manage to "modulate" a sine wave, and you just create AM (amplitud modulated) and FM (frequency modulated) waves. Congratulations!
https://www.shadertoy.com/view/lss3zs
Another interesting property of waves is their ability to add up. Comment/uncomment and tweak the following lines. Pay atention on how the frequencies and amplitudes change conform we add different waves.
https://www.shadertoy.com/view/4dXGDX
<div class="simpleFunction" data="
float amplitud = 1.;
float frequency = 1.;
y = amplitud * sin(x * frequency);
float t = 0.01*(-u_time*130.0);
y += sin(x*2.1 + t)*4.5;
y += sin(x*1.72 + t*1.121)*4.0;
y += sin(x*2.221 + t*0.437)*5.0;
y += sin(x*3.1122+ t*4.269)*2.5;
y *= 0.06;
"></div>
https://www.shadertoy.com/view/XsXGz2
* Experiment by changing their values.
* Is it possible to cancel two waves? how that will look like?
* Is it possible to add waves in such a way that they will amplify each other?
https://www.shadertoy.com/view/lls3D7
In music, each note is asociated with specific a frequency. This frequencies seams to respond to a pattern where it self in what we call scale.
https://www.shadertoy.com/view/XdB3DD
By adding different iterations of noise (*octaves*), where in each one increment the frequencies (*Lacunarity*) and decreasing amplitude (*gain*) of the **noise** we can obtain a bigger level of granularity on the noise. This technique is call Fractal Brownian Motion (*fBM*) and in it simplest form looks like the following code
https://www.shadertoy.com/view/XdBSWw
<div class="simpleFunction" data="// Properties
const int octaves = 1;
float lacunarity = 2.0;
float gain = 0.5;
//
// Initial values
float amplitud = 0.5;
float frequency = x;
//
// Loop of octaves
for (int i = 0; i < octaves; i++) {
&#9;y += amplitud * noise(frequency);
&#9;frequency *= lacunarity;
&#9;amplitud *= gain;
}"></div>
https://www.shadertoy.com/view/llfGD2
* Progressively change the number of octaves to iterate from 1 to 2, 4, 8 and 10. See want happens.
* With over 4 octaves try changing the lacunarity value.
* Also with over 4 octaves change the gain value and see what happens.
https://www.shadertoy.com/view/Mlf3RX
Note how each in each octave the noise seams to have more detail. Also note the self similarity while more octaves are added.
The following code is an example of how fBm could be implemented on two dimensions.
<div class='codeAndCanvas' data='2d-fbm.frag'></div>
* Reduce the numbers of octaves by changing the value on line 37
* Modify the lacunarity of the fBm on line 47
* Explore by changing the gain on line 48
This techniques is use commonly to construct procedural landscapes. The self similarity of the fBm is perfect for mountains. If you are interested in this use you defenetly should read [this great article of Inigo Quiles about advance noise](http://www.iquilezles.org/www/articles/morenoise/morenoise.htm).
![Blackout - Dan Holdsworth (2010)](holdsworth.jpg)
Using escentially the same technique is also possible to obtain other effect like what is known as **turbulence**. It's esentially a fBm but constructed from the absolute value of a signed noise.
```glsl
for (int i = 0; i < OCTAVES; i++) {
value += amplitud * abs(snoise(st));
st *= 2.;
amplitud *= .5;
}
```
<a href="../edit.html#13/turbulence.frag"><img src="turbulence-long.png" width="520px" height="200px"></img></a>
Another member of this family of algorithms is the **ridge**. Constructed similarly to the turbolence but with some extra calculations:
```glsl
n = abs(n); // create creases
n = offset - n; // invert so creases are at top
n = n * n; // sharpen creases
```
<a href="../edit.html#13/ridge.frag"><img src="ridge-long.png" width="520px" height="200px"></img></a>
### Domain Warping
[Inigo Quiles wrote this other fascinating article](http://www.iquilezles.org/www/articles/warp/warp.htm) about how is possible to use fBm to warp a space of a fBm. Mind blowing, Right? Is like the dream inside the dream of Inception.
![ f(p) = fbm( p + fbm( p + fbm( p ) ) ) - Inigo Quiles (2002)](quiles.jpg)
A mild example of this technique is the following code where the wrap is use to produce something this clouds-like texture. Note how the self similarity propertie still is apreciated.
<div class='codeAndCanvas' data='clouds.frag'></div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 KiB

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

Loading…
Cancel
Save