Translated the first 7 chapters to spanish

pull/51/head
necsoft 8 years ago
parent 90248c8060
commit c7d9544f9d

@ -0,0 +1,48 @@
# Introducción
<canvas id="custom" class="canvas" data-fragment-url="cmyk-halftone.frag" data-textures="vangogh.jpg" width="700px" height="320px"></canvas>
Las imágenes que aparecen arriba fueron creadas de diferentes formas. La primera fue hecha por la mano de Van Gogh, aplicando capa por capa la pintura. Le tomó horas pintarla. La segunda fue producida en segundos mezclando cuatro matrices de pixeles: una para el cyan, otra para el magenta, otra para el amarillo y otra para el negro. La diferencia clave entre ambas es que la segunda imágen fue hecha de una manera no serializada (es decir que el proceso no fue paso a paso, sino de manera simultánea).
Este libro trata sobre una técnica computacional revolucionaria, que lleva a las imágenes generadas digitalmente a un nuevo nivel, los *fragment shaders*. Esta revolución es comparable a lo que fue en su momento la imprenta de Gutemberg para la gráfica.
![Imprenta de Gutenberg](gutenpress.jpg)
Los fragment shaders te dan un control total sobre los pixeles renderizados en la pantalla, a una super velocidad. Este es el motivo por el que se usa en todo tipo de casos, desde filtros de video, hasta increíbles videojuegos en 3D.
![Journey por That Game Company](journey.jpg)
En los próximos capítulos descubrirás cuán increíblemente rápida y poderosa es esta técnica, y cómo incorporarla a tu trabajo personal o profesional.
## ¿Para quién es este libro?
Este libro está escrito para creative coders, desarrolladores de videojuegos e ingenieros que tengan alguna experiencia con la programación, un conocimiento básico de álgebra lineal y trigonometría, y que quieran llevar su trabajo a un nuevo y emocionante nivel gráfico. (Si te interesa aprender a programar, te recomiendo comenzar con [Processing](https://processing.org/) y volver cuando te sientas cómodo).
Este libro te enseñará a integrar shaders en tus proyectos, mejorando la performance y la calidad gráfica. Como los shaders GLSL (OpenGL Shading Language) se pueden compilar y correr en diferentes plataformas, podrás aplicar lo que aprendas aquí en cualquier entorno que que use OpenGL, OpenGL ES o WebGL. En otras palabras podrás utilizarlo en sketches de [Processing](https://processing.org/), aplicaciones de [openFrameworks](http://openframeworks.cc/), instalaciones interactivas con [Cinder](http://libcinder.org/), incluso en web o en juegos iOS/Android con [Three.js](http://threejs.org/).
## ¿Qué temas se tratan en este libro?
Este libro se enfoca en el uso de los pixel shaders GLSL. Primero definiremos qué son los shaders; luego aprenderemos a crear formas procedurales, patrones, texturas y animaciones con ellos. Aprenderás los fundamentos básicos del lenguaje y cómo aplicarlos en escenarios más útiles cómo: el procesamiento de imágenes (operaciones de imágen, convoluciones de matrices, desenfocado, filtros de color, lookup tables y otros efectos) y simulaciones (El juego de la vida de Conway, la reacción-difusión de Gray-Scott, ondas de agua, efecto de acuarela, celdas de Voronoi, etc). Hacia el final del libro veremos un conjunto de técnicas avanzadas basadas en ray marching.
*Habrá ejemplos interactivos en cada uno de los capítulos para que puedas jugar con ellos.* Cuando modifiques el código, podrás ver al instante los cambios reflejados en la pantalla. Los conceptos expuestos pueden ser abstractos y confusos, por lo que los ejemplos interactivos son esenciales para comprender el material. Cuanto más rápido pongamos manos a la obra en el código, mejor lo entenderemos.
Que cosas no vas a encontrar en este libro:
* Este *no es* un libro sobre OpenGL o webGL. OpenGL/webGL son temas mucho mas grandes que GLSL o el uso fragment shaders. Si estás interesado en aprender openGL/webGL te recomiendo mirar: [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) (también conocido como el libro rojo) 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)
* Este *no es* un libro de matemáticas. A pesar de que cubriremos un número de algoritmos y técnicas que están íntimimante relacionados con el álgebra y la trigonometría, no las explicaremos en profundidad. Si tienes alguna duda con respecto a la mátemática empleada en este libro te recomiendo tener cerca alguno de estos libros: [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) o [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).
## ¿Qué necesito para comenzar?
¡No mucho! Si tienes algún navegador que cuente con WebGL (como por ejemplo Chrome, Firefox o Safari) y una conexión a internet, solo necesitas hacer click en "Siguiente" para poder comenzar.
Alternativamente, dependiendo cuales sean tus necesidades puedes:
- [Crear una versión offline del libro](http://thebookofshaders.com/appendix/)
- [Correr los ejemplos en una RaspberryPI sin un navegador](http://thebookofshaders.com/appendix/)
- [Crear un PDF del libro para imprimir.](http://thebookofshaders.com/appendix/)
- Usar el [repositorio on-line](https://github.com/patriciogonzalezvivo/thebookofshaders) y ayudarnos a resolver problemas y compartir código.

@ -0,0 +1,48 @@
# Comenzando
## Qué es un fragment shader?
En el capítulo anterior comparamos a los shaders con la invención de la imprenta de Gutenberg. ¿Por qué? Y mas importante: ¿Qué es un shader?
![From Letter-by-Letter, Right: William Blades (1891). To Page-by-page, Left: Rolt-Wheeler (1920).](print.png)
Si ya tienes experiencia dibujando con computadoras, sabrás que en ese proceso dibujas un círculo, luego un rectángulo, una línea, algunos triángulos, hasta que por fin compones la imágen que querías. Ese proceso es muy similar a escribir una carta o un libro a mano, es un conjunto de instrucciones, una tarea después de la otra.
Los shaders son también un conjunto de instrucciones, pero estas son ejecutadas todas al mismo tiempo por cada pixel de la pantalla. Eso significa que el código que escribes tiene que comportarse de manera diferente dependiendo de su posición en la pantalla. Como una prensa tipográfica, tu programa trabajará como una función que recibe posición y devuelve color, y que al ser compilada se ejecutará a una velocidad extraordinaria.
![Prensa tipográfica china](typepress.jpg)
## Por qué son rápidos los shaders?
Para responder esto hay que hablar de las maravillas del *parallel processing*.
Imagina que tu CPU es un gran tubo industrial y que cada tarea pasa por ahi como si fuese una linea de producción. Algunas tareas son mas grandes que otras, esto quiere decir que algunas consumen mas tiempo y energía que el resto. Solemos decir que estas tareas requieren mas tiempo de proceso. Debido a la arquitectura de las computadoras estas tareas son forzadas a correr en serie; cada trabajo debe ser terminado, uno después del otro. Las computadoras modernas usualmente cuentan con un grupo de procesadores que trabajan como estos tubos, completando tareas, una después de la otra. Cada uno de estos tubos es también conocido como *thread*.
![CPU](00.jpeg)
Los videojuegos y otras aplicaciones gráficas requieren mucho mas tiempo de proceso que otros programas. Debido a su contenido gráfico es necesario hacer muchas operaciones numéricas por pixel. Cada pixel de la pantalla necesita ser computado, y en el caso de los videojuegos en 3D también hay que calcular las geometrías y las perspectivas.
Volvamos a pensar en la metáfora de los tubos y las tareas. Cada pixel de la pantalla representa una pequeña tarea a realizar. Individualmente cada tarea no es un gran problema para el CPU, pero (y aquí esta el problema) ¡Esta pequeña tarea deberá ser ejecutada por cada pixel! Eso significa que en una antigua pantalla de 800x600 pixeles ¡Tendremos que procesar 480000 pixeles por frame, es decir 14400000 cálculos por segundo! ¡Si! Ese es un problema lo suficientemente grande como para sobrecargar al microprocesador. En una pantalla retina display moderna de 2880x1800 pixeles, corriendo a 60 frames por segundo, los cálculos aumentarían a 311040000 por segundo. ¿Cómo hicieron los ingenieros gráficos para solucionar este problema?
![](03.jpeg)
Aquí es donde procesar en paralelo se vuelve una buena solución. En vez de tener un par de procesadores grandes y poderosos, o *tubos*, es mucho mas inteligente tener muchos pequeños procesadores funcionando en paralelo al mismo tiempo. Eso es la GPU (Graphic Processor Unit).
![GPU](04.jpeg)
Imagina que los pequeños procesadores conforman una mesa de tuberías, y que la información de cada pixel es una pelota de ping pong. 14400000 pelotas de ping pong en un segundo pueden obstruir a cualquier tubería, pero si en cambio es una mesa de 800x600 tuberías y recibe 30 olas de 480000 pixeles por segundo, se puede manejar de una manera fluída sin problemas. Esto funciona de la misma manera con resoluciones mas grandes, cuanto mas hardware en paralelo tengas, es mayor el flujo de pixeles que se puede manejar.
Otro "superpoder" de la GPU es que algunas funciones matemáticas especiales son aceleradas via hardware, la matemática mas compleja es solucionada directamente en el microchip en vez resolverlo en el software. Eso signfica que tendremos una velocidad extra en cálculos trigonométricos u operaciones de matrices que iran tan rápido como la electricidad.
## ¿Qué es GLSL?
GLSL es la sigla de openGL Shading Language, que es el standard específico de shaders que veremos en los próximos capítulos. Hay otros tipos de shaders que varían dependiendo del hardware y del sistema operativo. Aquí trabajaremos con las especificaciones reguladas por el [Khronos Group](https://www.khronos.org/opengl/). Entender la historia de OpenGL puede ser útil para comprender la mayoría de las convenciones raras, te recomiendo echarle un vistazo a: [openglbook.com/chapter-0-preface-what-is-opengl.html](http://openglbook.com/chapter-0-preface-what-is-opengl.html)
## ¿Por qué los shaders tienen mala reputación?
Como dijo el tio Ben "un gran poder conlleva una gran responsabilidad", y la computación paralela sigue esta regla; el poderoso diseño de arquitectura de la GPU viene con sus propias limitaciones y restricciones.
Para que cada tubo, o thread, pueda correr en paralelo es necesario que cada uno sea independiente del otro. Es decir que los threads son *ciegos* y no saben lo que los demás threads están haciendo. Esta restricción implica que toda la información debe fluir en la misma dirección, por lo tanto es imposible conocer el resultado de otro thread. Permitir la comunicación entre threads pondría en riesgo la integridad de los datos.
Además la GPU deja constantemente ocupados a los micro-procesadores (los tubos); tan pronto como terminan una tarea reciben nueva información para procesar. Es imposible para cada thread saber lo que estaba haciendo en el momento previo. Se podría dibujar un botón de una UI de un sistema operativo, luego renderizar una porción del cielo de un videojuego, y a continuación mostrar el texto de un mail. Cada thread no solamente es **ciego** sino que **tampoco tiene memoria**. Mas alla de la abstracción necesaria para poder crear una función que cambie de resultado pixel a pixel, dependiendo de su posición, la incapacidad de ver a los demás threads y la falta de memoria, hacen que los shaders no sean muy populares entre los programadores principiantes.
¡No te preocupues! En los próximos capítulos aprenderemos paso a paso, desde los shaders mas sencillos a los casos mas avanzados. Si estás leyendo esto desde un navegador moderno, vas a poder jugar con los ejemplos interactivos. No esperes mas y presiona *Siguiente >>* para ir al próximo capítulo.

@ -0,0 +1,53 @@
## Hola mundo
Usualmente el "Hola mundo" es el primer ejemplo con el que se aprende un lenguaje de programación. Se trata de una simple linea de código que imprime un entusiasta mensaje de bienvenida.
En el mundo de las GPU renderizar texto es una tarea complicada para ser el primer paso, por lo tanto nosotros vamos a imprimir un brillante color de bienvenida para mostrar nuestro entusiasmo.
<div class="codeAndCanvas" data="hello_world.frag"></div>
Si estás leyendo este libro en un navegador, el código anterior es interactivo, eso significa que puedes hacer click y cambiar cualquier línea de código para explorar cómo funciona. Los cambios se reflejaran automáticamente gracias a que la arquitectura de la GPU se encarga de compilar y reemplazar los shaders al instante. Intenta modificar el contenido de la línea 6.
Aunque estas simples líneas de código no parezcan mucho, podemos inferir mucha información importante de ellas:
1. Los shaders tienen una función ```main``` principal que devuelven un color al final. Esto es muy similar a C.
2. El color final del pixel es guardado en la variable global reservada ```gl_FragColor```.
3. Este lenguaje similar a C tiene *variables* reservadas (como ```gl_FragColor```), *funciones* y *tipos de variables*. En este caso vemos que existe ```vec4``` que es un tipo de variable de 4 dimensiones de punto flotante. Mas adelante veremos otros tipos de variables como ```vec3``` y ```vec2``` junto con las populares: ```float```, ```int``` y ```bool```.
4. Si miramos detenidamente el ```vec4``` podemos inferir que los cuatro argumentos pasados son el canal RED (rojo), el canal GREEN (verde), el canal BLUE (azul) y el canal ALPHA (transparencia). Además podemos ver que los valores se encuentran *normalizados*, eso significa que van desde ```0.0``` a ```1.0```. Mas adelante aprenderemos que normalizar valores vuelve mucho mas fácil nuestro trabajo con las variables.
5. Otra *función de C* que vemos en el ejemplo son los macros al preprocesador. Los macros son parte del proceso de precompilado. Con ellos es posible definir variables globales (con ```#define```) y hacer operaciones condicionales básicas ( con ```#ifdef``` y ```#endif```). Todos los comandos macro comienzan con un numeral (```#```). La pre-compilación sucede en el momento previo a la compilación y chequea todos los ```#defines```, y los condicionales ```#ifdef``` (esta definido) y ```#ifndef``` (no esta definido). En nuestro ejemplo, el "Hola mundo", solamente insertamos la segunda línea de código si ```GL_ES``` esta definida, que la mayoría de las veces se encuentra definida cuando el código es compilado en mobile o en navegadores.
6. Los valores flotantes son vitales en los shaders, ya que el nivel de *precisión* es crucial. A menor precisión mayor velocidad de render, pero peor calidad. Podemos ser meticulosos y especificar la precisión de cada variable que use punto flotante. En la primera línea (```precision mediump float;```) estamos ajustando todos los valores flotantes a una precisión media. Pero podríamos configurarlos en low (```precision lowp float;```) o high (```precision highp float;```).
7. El último detalle, y quizá el mas importante, es que las especificaciones de GLSL no garantizan que las variables sean automáticamente convertidas. ¿Qué significa eso? Los manufacturadores de GPU tienen diferentes estrategias para acelerar los gráficos pero están forzados a entregar especificaciones mínimas, por lo que la conversión automática de variables no es algo importante. Si queremos que nuestro código sea consistente y no pasar horas depurando pantallas blancas, tenemos que acostumbrarnos a usar el punto ( ```.``` ) en los flotantes. Este código no siempre funcionará:
```glsl
void main() {
gl_FragColor = vec4(1,0,0,1); // ERROR
}
```
Ahora que ya describimos los elementos mas importantes de nuestro "Hola mundo", es hora de hacer click en el código y poner en práctica nuestros conocimientos aprendidos. Notarás que cuando hay errores, el programa no compilará, y mostrará una pantalla blanca. Aqui hay algunas cosas interesantes que puedes probar, por ejemplo:
* Intenta modificar los flotantes y poner enteros, es posible que tu placa de video no tolere esto.
* Prueba comentar la línea 6 y no asignar ningún valor a la función.
* Intenta crear una función separada que devuelva un color específico y usalo dentro del ```main()```. Una pista, aqui esta el código que usaríamos para devolver el color rojo:
```glsl
vec4 red(){
return vec4(1.0,0.0,0.0,1.0);
}
```
* Hay muchas formas de construir un ```vec4```, intenta descubrir nuevas formas de hacerlo. La siguiente es un ejemplo:
```glsl
vec4 color = vec4(vec3(1.0,0.0,1.0),1.0);
```
Mas alla de que el ejemplo no sea muy emocionante, es el ejemplo más básico que podemos crear - estamos cambiando todos los pixeles de la pantalla al mismo tiempo y asignándole a todos el mismo color. En el siguiente capítulo veremos cómo cambiar los colores de los pixeles utilizando dos tipos de entradas: espacio (la posición del pixel en la pantalla) y tiempo (el número de segundos desde que la página fue cargada).

@ -0,0 +1,61 @@
## Uniforms
Hasta ahora hemos vimos como la GPU maneja grandes números de threads en paralelo, cada uno responsable de asignar un color a una fracción de la pantalla. A pesar de que cada thread no conoce a los otros, necesitamos poder enviarle valores de entrada desde la CPU a todos los threads. Debido a la arquitectura de la GPU todos esos valores van a ser iguales (*uniform*) para todos los threads y de sólo lectura. En otras palabras, cada thread recibe las misma información y puede leerla pero no modificarla.
Estas entradas se llaman ```uniform``` y vienen en diferentes tipos: ```float```, ```vec2```, ```vec3```, ```vec4```, ```mat2```, ```mat3```, ```mat4```, ```sampler2D``` y ```samplerCube```. Los uniforms son definidos con sus correspondientes tipos, al principio del código, luego de definir la precisión del punto flotante.
```glsl
#ifdef GL_ES
precision mediump float;
#endif
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
```
Podemos imaginar que los uniforms son como pequeños puentes entra la CPU y la GPU. Los nombres varían dependiendo de cada implementación, en esta serie de ejemplos estoy usando ```u_time``` (tiempo en segundos desde que shaders comenzó a correr), ```u_resolution``` (el tamaño de la ventana donde se esta dibujando el shader) y ```u_mouse``` (la posición del mouse dentro de la ventana en pixeles). Estoy siguiendo la convención de utilizar ```u_``` antes del nombre del uniform, para ser explícito respecto a la naturaleza de la variable, pero encontrarás diferentes nombre de uniforms. Por ejemplo [ShaderToy.com](https://www.shadertoy.com/) utiliza las mismas uniforms pero con los siguientes nombres:
```glsl
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform vec4 iMouse; // mouse pixel coords. xy: current, zw: click
uniform float iGlobalTime; // shader playback time (in seconds)
```
Ya hemos hablado mucho, vamos a ver los uniforms en acción. En el código siguiente usamos ```u_time``` - el número de segundos desde que el shader comenzó a ejecutarse - junto con una función del seno para animar en transición la cantidad de rojo en la pantalla.
<div class="codeAndCanvas" data="time.frag"></div>
Como puedes ver, GLSL tiene mas sorpresas. La GPU tiene funciones de ángulo, de trigonometría y exponenciales, que son aceleradas por hardware: [```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) y [```clamp()```](../glossary/?search=clamp).
Es hora de jugar con el código de arriba:
* Reduce la frecuencia del cambio hasta que sea prácticamente imperceptible.
* Acelera la frecuencia hasta que dejes de ver el parpadeo.
* Juega con los canales de colores (RGB) en diferentes frecuencias, para obtener patrones y comportamientos interesantes.
## gl_FragCoord
De la misma forma que GLSL nos da por default la variable reservada ```vec4 gl_FragColor```, también nos da ```vec4 gl_FragCoord``` que guarda la coordenada del *pixel* o *screen fragment* del thread actual. Con ```vec4 gl_FragCoord``` podemos saber el lugar en la pantalla en el que el thread esta actualmente trabajando. En este caso esta variable no es un ```uniform``` porque será diferente en cada uno de los threads, las variables que cambian en cada thread ,como ```gl_FragCoord```, son *varying*.
<div class="codeAndCanvas" data="space.frag"></div>
En el código de arriba *normalizamos* la coordenada del fragment, dividiéndolo por la resolución total de la ventana. Una vez que hicimos este proceso, la posición va de 0.0 a 1.0, lo que vuelve mucho más fácil de usar estos valores en los canales RED (rojo) y GREEN (verde).
En el mundo de los shaders no tenemos muchas herramientas para hacer debug mas allá de asignar colores e intentar encontrarles el sentido. Muchas veces verás que programar en GLSL es como poner barcos dentro de botellas, cuanto más complicado, mas hermoso y gratificante es.
![](08.png)
Es hora de poner en práctica los conocimientos aprendidos.
* ¿Podrías decir dónde está nuestro ```(0.0,0.0)``` en la pantalla?
* ¿Y dónde está ```(1.0,0.0)```, ```(0.0,1.0)```, ```(0.5,0.5)``` y ```(1.0,1.0)```?
* ¿Puedes imaginar cómo usar ```u_mouse``` sabiendo que los valores estan en pixeles no están normalizados? ¿Podrías usarlo para mover los colores?
* ¿Te imaginas alguna forma interesante de combinar ```u_time``` y ```u_mouse``` para generar patrones ?
Luego de hacer estos ejercicios seguramente te preguntarás que mas puedes hacer con los superpoderes que los shaders te dan. En el próximo capítulo veremos como crear tus propios shaders en three.js, Processing y openFrameworks.

@ -0,0 +1,159 @@
## Ejecutando tu shader
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 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.
### En **Three.js**
El brillante y humilde Ricardo Cabello (también conocido como [MrDoob](https://twitter.com/mrdoob)) ha estado desarrollando junto con otros [contribuidores](https://github.com/mrdoob/three.js/graphs/contributors) probablemente el framework más conocido de WebGL, llamado [Three.js](http://threejs.org/). Encontrarás muchos ejemplos, libros y tutoriales para aprender a hacer cosas geniales en 3D con JavaScript.
Aqui abajo hay un ejemplo del HTML y JS necesario para poder empezar a utilizar shaders con three.js. Presta atención al script```id="fragmentShader"```, aqui es donde puedes copiar los ejemplos de este 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>
```
### En **Processing**
Iniciado por [Ben Fry](http://benfry.com/) y [Casey Reas](http://reas.com/) en 2001, [Processing](https://processing.org/) es un extraordinario y poderoso entorno en el que se puede aprender los primeros pasos con el código (al menos así fue para mí). [Andres Colubri](https://codeanticode.wordpress.com/) ha hecho importantes cambios a la parte de OpenGL y video, logrando que sea más fácil y amigable utilizar shaders GLSL. Processing buscará el archivo ```"shader.frag"``` en la carpeta ```data``` del sketch. En ese archivo debes poner los ejemplos que encuentres en este libro.
```processing
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);
}
```
Para hacer funcionar el shader en versiones previas a la 2.1, necesitas agregar la siguiente línea al comienzo de tu shader: ```#define PROCESSING_COLOR_SHADER```. Así es como quedarí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);
}
```
Para más información sobre shaders en processing puedes chequear este [tutorial](https://processing.org/tutorials/pshader/).
### En **openFrameworks**
Todos tienen un lugar en el que se sienten mas cómodos, en mi caso, todavía sigue siendo [openFrameworks](http://openframeworks.cc/). Este framework en C++ engloba openGL y otras librerías open source. En muchos puntos es muy parecido a Processing, pero con las complicaciones obvias de trabajar con los compiladores de C++. De la misma forma que Processing, openFrameworks buscará tus shaders en archivos de la carpeta data, no te olvides de copiar los archivos ```.frag``` que quieres usar y cambiar el nombre cuando los cargas.
```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();
}
```
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/).

@ -0,0 +1,143 @@
# Dibujando con algoritmos
## Funciones de forma
Este capítulo se podría llamar "La lección de la cerca del Sr Miyagi". Anteriormente normalizamos la posición de x e y al canal de rojo y verde. Esencialmente creamos una función que tomaba dos vectores dimensionales (x e y) y devolvía un vector de cuatro dimensiones (rojo, verde, azul y transparencia). Pero antes de ir mas lejos, transformando valores entre dimensiones, necesitamos comenzar con algo sencillo... mucho mas sencillo. Eso significa comprender las funciones unidimensionales. A mayor tiempo y energía que pongas en aprender esto, mejor será tu karate.
![The Karate Kid (1984)](mr_miyagi.jpg)
El siguiente código va a ser nuestra cerca. Dentro del código visualizamos el valor normalizado de la coordenada *x* (```st.x```) de dos maneras: una visualizando el brillo (observa el bonito gradiente de fondo del negro al blanco) y otra dibujando una línea verde arriba (en este caso el valor de *x* es asignado directamente al valor de *y*). No te enfoques mucho en la función plot, la veremos en detalle en unos momentos.
<div class="codeAndCanvas" data="linear.frag"></div>
**Nota rápida**: el constructor de ```vec3``` "entiende" que quieres asignar tres colores con la misma variable, mientras que el ```vec4``` entiende que quieres crear un vector tridimensional con un cuarto valor (en este caso el que controla el alpha). Mira por ejemplo la línea 20 y la 26 de arriba.
Este código es tu cerca; es importante observarlo y entenderlo. Volverás aquí una y otra vez, a este espacio entre el *0.0* y el *1.0*. Aprenderás el arte de doblar y dar forma a esta línea.
Esta relación par entre *x* e *y* (o el brillo) es conocida como *interpolación lineal*. Desde aquí podemos utilizar funciones matemáticas para darle *forma* a esta línea. Por ejemplo podemos elevar *x* a la quinta potencia para generar una línea curva.
<div class="codeAndCanvas" data="expo.frag"></div>
Interesante ¿No? En la línea 19 puedes probar diferentes exponentes: 20.0, 2.0, 1.0, 0.0, 0.2 o 0.02 por ejemplo. Entender esta relación entre el valor y el exponente nos será muy útil. Usar este tipo de funciones matemáticas aquí y allá nos dará un control expresivo sobre nuestro código, como si fuese un tipo de acupuntura con el que manejas el flujo de los valores.
[```pow()```](../glossary/?search=pow) es una función nativa en GLSL y hay muchas mas. La mayoría de ellas son aceleradas por hardware, lo que significa que, usadas de la forma correcta, harán tu código mucho mas rápido.
Reemplaza la función de la línea 19. Prueba otras como: [```exp()```](../glossary/?search=exp), [```log()```](../glossary/?search=log) y [```sqrt()```](../glossary/?search=sqrt). Algunas de estas funciones son mucho mas interesantes cuando las usamos con PI. En la línea 5 definí un macro que reemplaza cualquier llamado a ```PI``` por el valor ```3.14159265359```.
### Step y Smoothstep
GLSL también cuenta con algunas funciones únicas de interpolación, que también son aceleradas por hardware.
La interpolación [```step()```](../glossary/?search=step) recibe dos parámetros. El primero es el límite o umbral, el segundo es el valor que queremos chequear. Cualquier número por debajo del límite devuelve ```0.0``` todo lo que lo supere devuelve ```1.0```.
Intenta cambiar el límite en la línea 20 del siguiente código.
<div class="codeAndCanvas" data="step.frag"></div>
La otra función única es el [```smoothstep()```](../glossary/?search=smoothstep). Dado un rango de dos números y un valor, esta función interpola el valor entre el rango definido. Los primeros dos parámetros son para el comienzo y el final de la transición, el tercero es el valor a interpolar.
<div class="codeAndCanvas" data="smoothstep.frag"></div>
En el anterior ejemplo, en la línea 12, hemos usado smoothstep para dibujar una línea verde en la función ```plot()```. Por cada posición en el eje x esta función crea una salto en un valor particular de y. ¿Cómo? Conectando dos [```smoothstep()```](../glossary/?search=smoothstep) juntos. Observa la siguiente función y reemplaza la línea 20 por esta, y piensa en ella como un corte vertical. El fondo de parece a una línea ¿No?
```glsl
float y = smoothstep(0.2,0.5,st.x) - smoothstep(0.5,0.8,st.x);
```
### Seno y Coseno
Cuando queremos usar un poco de matemática para animar, dar forma o mezclar valores, no hay nada mejor que ser amigos del seno y del coseno.
Estas dos funciones básicas trigonométricas trabajan juntas creando círculos y son mas útiles que la navaja suiza de MacGyver. Es importante saber como se comportan y de que forma pueden ser combinadas. En pocas palabras, dado un ángulo (en radianes) devolverán la posición de *x* ([coseno](../glossary/?search=cos)) e y ([seno](../glossary/?search=sin)) de un punto en el borde de un círculo con un radio igual a 1. Como estas funciones devuelven un valor normalizado (entre -1 y 1) y suavizado, terminan siendo una herramienta increíble.
![](sincos.gif)
Como es difícil describir la relación entre las funciones trigonométricas y los círculos, la hermosa animación de arriba hace el trabajo de explicarlo visualmente.
<div class="simpleFunction" data="y = sin(x);"></div>
Presta mucha atención a esta curva sinusoidal. Nota como los valores de Y fluyen suavemente entre -1 y 1. Como vimos en el anterior capítulo, podemos utilizar el comportamiento rítmico de [```sin()```](../glossary/?search=sin) para animar propiedades. Si estás leyendo este ejemplo en un navegador, puedes modificar la fórmula que aparece aquí arriba y ver cómo cambia la onda. (Nota: No olvidar el punto y coma al final.)
Completa los siguientes ejercicios y presta atención a lo que sucede:
* Suma el tiempo (```u_time```) a *x* antes de computar el ```sin```. Observa detenidamente ese **movimiento** a lo largo de *x*.
* Multiplica *x* por ```PI``` antes de computar el ```sin```. Nota como las dos fases se **encogen** y cada ciclo se repite dos veces.
* Multiplica el tiempo (```u_time```) por *x* antes de computar el ```sin```. Observa como la **frecuencia** entre las fases se comprime mas y mas. Nota que u_time en un momento pasa a ser un número muy alto y se hace difícil ver el gráfico.
* Suma 1.0 a [```sin(x)```](../glossary/?search=sin). Observa como toda la onda es **desplazada** hacia arriba y ahora todos los valores van de 0.0 a 2.0.
* Multiplica [```sin(x)```](../glossary/?search=sin) por 2.0. Mira como la **amplitud** duplica su tamaño.
* Calcula el valor absoluto ([```abs()```](../glossary/?search=abs)) de ```sin(x)```. Observa como se parece a la trayectoria de una pelota **rebotando**.
* Extrae sólo la parte fraccionaria ([```fract()```](../glossary/?search=fract)) del resultado de [```sin(x)```](../glossary/?search=sin).
* Suma el mayor entero mas cercano ([```ceil()```](../glossary/?search=ceil)) y el menor entero mas cercano ([```floor()```](../glossary/?search=floor)) del resultado de [```sin(x)```](../glossary/?search=sin) para obtener la onda digital de 1.0 y -1.0.
### Otras funciones útiles
Al final del último ejercicio hemos introducido algunas funciones nuevas. Ahora es el momento de experimentar con cada una descomentenando las siguientes lineas, de a una. Es importante entender estas funciones y estudiar como se comportan. Ya lo sé ¿Para qué? Si buscas rápidamente en Google "Arte Generativo" vas a entender el porque. Ten en cuenta que estas funciones son nuestra cerca. Estamos dominando el movimiento en una sola dimensión, arriba y abajo. ¡Pronto, será el momento de agregar la segunda, la tercera y la cuarta dimensión!
![Anthony Mattox (2009)](anthony-mattox-ribbon.jpg)
<div class="simpleFunction" data="y = mod(x,0.5); // return x modulo of 0.5
//y = fract(x); // return only the fraction part of a number
//y = ceil(x); // nearest integer that is greater than or equal to x
//y = floor(x); // nearest integer less than or equal to x
//y = sign(x); // extract the sign of x
//y = abs(x); // return the absolute value of x
//y = clamp(x,0.0,1.0); // constrain x to lie between 0.0 and 1.0
//y = min(0.0,x); // return the lesser of x and 0.0
//y = max(0.0,x); // return the greater of x and 0.0 "></div>
### Funciones de forma avanzadas
[Golan Levin](http://www.flong.com/) tiene en su página documentación muy útil sobre cómo generar formas complejas con funciones. Trasladar estas funciones a GLSL es una muy buena forma de comenzar a generar nuestras propias piezas de código.
* [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/)
Como los chefs que colectan especias e ingredientes exóticos, los artistas digitales y creative coders tienen un amor particular por crear sus propias funciones de dibujo.
[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)
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.
<iframe width="800" height="450" frameborder="0" src="https://www.shadertoy.com/embed/XsXXDn?gui=true&t=10&paused=true" allowfullscreen></iframe>
En el *Siguiente >>* capítulo comenzaremos a usar nuevos movimientos. Primero mezclaremos color y luego dibujaremos formas.
#### Ejercicio
Presta atención a la siguiente tabla de ecuaciones hecha por [Kynd](http://www.kynd.info/log/). Observa como combina las funciones y sus propiedades para controlar los valores de 0.0 a 1.0. Ahora es el momento de practicar replicando estas funciones. Recuerda que cuanto más practiques esto, mejor será tu karate.
![Kynd - www.flickr.com/photos/kynd/9546075099/ (2013)](kynd.png)
#### Para tu caja de herramientas
Estas son algunas herramientas que te ayudaran a visualizar este tipo de funciones.
* Grapher: si tienes una computadora con Mac OS, escribe ```grapher``` en tu spotlight y podrás usar esta herramienta super útil.
![OS X Grapher (2004)](grapher.png)
* [GraphToy](http://www.iquilezles.org/apps/graphtoy/): una vez mas [Iñigo Quilez](http://www.iquilezles.org) ha creado una herramienta para visualizar funciones GLSL en WebGL.
![Iñigo Quilez - GraphToy (2010)](graphtoy.png)
* [Shadershop](http://tobyschachman.com/Shadershop/): esta herramienta increíble creada por [Toby Schachman](http://tobyschachman.com/) te enseñará a consturir funciones complejas de una manera intuitiva y visual.
![Toby Schachman - Shadershop (2014)](shadershop.png)

@ -0,0 +1,140 @@
## Colores
![Paul Klee - Color Chart (1931)](klee.jpg)
No hemos tenido oportunidad todavía de hablar sobre los tipos de vectores en GLSL. Antes de ir mas lejos, es importante entender cómo funcionan estas variables, hablar de colores es una buena forma de entenderlos.
Si te encuentras familiarizado con la programación orientada a objetos, probablemente te habrás dado cuenta que estamos accediendo a los valores de los vectores, como si fuese un ```struct``` de C.
```glsl
vec3 red = vec3(1.0,0.0,0.0);
red.x = 1.0;
red.y = 0.0;
red.z = 0.0;
```
Definir los colores usando *x*, *y* y *z* puede ser muy confuso y engañoso. Es por eso que hay otras formas de acceder a esos valores, con nombres diferentes. Los valores de ```.x```, ```.y``` y ```.z```, se pueden llamar también ```.r```, ```.g``` y ```.b```, o también ```.s```, ```.t``` y ```.p``` (```.s```, ```.t``` y ```.p``` son usados para coordenadas espaciales de texturas, lo veremos en otro capítulo). También podemos acceder a un valor de los vectores, usando índices de posición,```[0]```, ```[1]``` y ```[2]```.
En las siguientes lineas puedes ver todas las formas de acceder al mismo valor.
```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;
```
Las diferentes formas de acceder a las variables son sólo nomenclaturas diseñadas para que el código sea mas claro. Esta flexibilidad de los shaders, es una puerta de entrada para poder relacionar el color con las coordenadas en el espacio.
Otra estupenda funcionalidad de los vectores en GLSL, es que las propiedades se pueden combinar en el orden que quieras, lo que hace muy sencillo manipular y mezclar valores. Esta habilidad es conocida como *swizzle*.
```glsl
vec3 yellow, magenta, green;
// Making Yellow
yellow.rg = vec2(1.0); // Assigning 1. to red and green channels
yellow[2] = 0.0; // Assigning 0. to blue channel
// Making Magenta
magenta = yellow.rbg; // Assign the channels with green and blue swapped
// Making Green
green.rgb = yellow.bgb; // Assign the blue channel of Yellow (0) to red and blue channels
```
#### Para tu caja de herramientas
Quizás no estás acostumbrado a seleccionar colores usando números - puede ser un poco confuso. Por suerte, hay muchísimos programas que nos hacen este trabajo mucho mas sencillo. Encuentra el que mas se adapte a tus necesidades y úsalo para trabajar con colores en formato vec3 o vec4. Por ejemplo, estos son los templates que uso en [Spectrum](http://www.eigenlogik.com/spectrum/mac):
```
vec3({{rn}},{{gn}},{{bn}})
vec4({{rn}},{{gn}},{{bn}},1.0)
```
### Mezclando color
Ahora que sabes como se definen los colores, es hora de integrar esto con lo que aprendimos previamente. En GLSL hay una función muy útil, [```mix()```](../glossary/?search=mix), que te permite mezclar dos valores en porcentaje. ¿Puedes adivinar cuál es el rango de porcentaje? ¡Si, valores de 0.0 a 1.0! Lo cual es perfecto para ti, porque luego de esas largas horas practicando tus movimientos de karate en la cerca. ¡Ahora es el momento de usar esos conocimientos!
![](mix-f.jpg)
Echa un vistazo al siguiente código en la línea 18 y observa cómo estamos usando los valores absolutos de una onda sinusoidal para mezclar ```colorA``` y ```colorB```.
<div class="codeAndCanvas" data="mix.frag"></div>
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.
### Jugando con gradientes
La función [```mix()```](../glossary/?search=mix) tiene mucho para ofrecer. En vez de usar un sólo ```float```, podemos pasarle variables en los dos primeros argumentos, en nuestro caso un ```vec3```. Haciendo esto podemos controlar los porcentajes de cada canal de color, ```r```, ```g``` y ```b```.
![](mix-vec.jpg)
Mira el siguiente ejemplo, como en los del capítulo anterior, estamos conectando la transición normalizada de la coordenada *x* y visualizándola con una línea. Ahora todos los canales van por la misma línea.
Ahora descomenta la línea 25 y mira lo que sucede. Luego descomenta las lineas 26 y 27. Recuerda que con las lineas visualizamos la cantidad de ```colorA``` y ```colorB``` a mezclar por cada canal.
<div class="codeAndCanvas" data="gradient.frag"></div>
Probablemente reconoces las tres funciones de forma que usamos en las lineas 25 y 27. ¡Juega con ellas! Es hora de mezclar y explorar lo aprendido en el capítulo previo para crear gradientes interesantes. Prueba hacer los próximos ejercicios:
![William Turner - The Fighting Temeraire (1838)](turner.jpg)
* Crea un gradiente que se parezca a atardecer de William Turner.
* Crea una transición entre el atardecer y el amanecer usando ```u_time```.
* ¿Puedes crear un arcoíris con lo que hemos aprendido hasta ahora?
* Usa la función ```step()``` para crear una bandera colorida.
### HSB
No podemos hablar de color sin mencionar el espacio de color. Probablemente sabes que hay diferentes formas de organizar un color mas allá de usar los canales de rojo, verde y azul.
[HSB](http://en.wikipedia.org/wiki/HSL_and_HSV) significa Hue (tono), Saturation (saturación) y Brightness (brillo o valor), es una forma útil y mas intuitiva de organizar el color. Tomate un momento para leer las funciones ```rgb2hsv()``` y ```hsv2rgb()``` del código siguiente.
Conectando la posición del eje x al tono y la posición del eje y al brillo podemos obtener este bonito espectro del color visible. La distribución espacial del color puede sernos muy útil; es mas intuitivo seleccionar un color usando HSB que con RGB.
<div class="codeAndCanvas" data="hsb.frag"></div>
### HSB en coordenadas polares
HSB fue originalmente diseñado para ser representado en coordenadas polares (basadas en el ángulo y el radio) en vez de coordenadas cartesianas (basadas en x e y). Para asociar nuestra función HSB a coordenadas polares necesitamos obtener el ángulo y la distancia del centro de la ventana. para hacer eso usaremos la función [```length()```](../glossary/?search=length) y [```atan(y,x)```](../glossary/?search=atan) (que es la versión en GLSL del comunmente usado ```atan2(y,x)```).
Cuando usamos vectores y funciones trigonométricas, ```vec2```, ```vec3``` y ```vec4``` son tratados como vectores, incluso cuando representan colores. Comenzaremos a tratar a los colores y a los vectores de una manera similar, de hecho te darás cuenta que es un concepto muy poderoso y flexible.
**Nota:** Si te preguntabas si había mas funciones geométricas además de [```length```](../glossary/?search=length): [```distance()```](../glossary/?search=distance), [```dot()```](../glossary/?search=dot), [```cross```](../glossary/?search=cross), [```normalize()```](../glossary/?search=normalize), [```faceforward()```](../glossary/?search=fraceforward), [```reflect()```](../glossary/?search=reflect) y [```refract()```](../glossary/?search=refract). También GLSL tiene funciones relacionadas a los vectores como: [```lessThan()```](../glossary/?search=lessThan), [```lessThanEqual()```](../glossary/?search=lessThanEqual), [```greaterThan()```](../glossary/?search=greaterThan), [```greaterThanEqual()```](../glossary/?search=greaterThanEqual), [```equal()```](../glossary/?search=equal) y [```notEqual()```](../glossary/?search=notEqual).
Una vez que obtenemos el ángulo y la longitud, necesitamos "normalizar" sus valores al rango de 0.0 a 1.0. En la línea 27, [```atan(y,x)```](../glossary/?search=atan) devolverá el angulo en radianes entre -PI y PI (-3.14 a 3.14), por lo que necesitamos dividir este número por ```TWO_PI``` (declarado arriba en nuestro código) para obtener valores de -0.5 a 0.5, que con una simple suma podemos transformar al rango deseado de 0.0 a 1.0. El radio devolverá un máximo de 0.5 (porque estamos calculando la distancia desde el centro del viewport) por lo tanto necesitamos duplicar este rango (multiplicándolo por dos) para obtener un máximo de 1.0.
Como podrás notar, todo se trata de transformar y manipular rangos de 0.0 a 1.0.
<div class="codeAndCanvas" data="hsb-colorwheel.frag"></div>
Intenta resolver los próximos ejercicios:
* Modifica el ejemplo polar, para obtener una rueda que gire, como el ícono de cargando.
* Usa una función de forma junto con la conversión de HSB a RGB para expandir un color en particular y encoger el resto.
![William Home Lizars - Red, blue and yellow spectra, with the solar spectrum (1834)](spectrums.jpg)
* Si miras detenidamente el círculo cromático usado en los goteros de color (ver la imágen de abajo), usan un espectro diferente, se trata del RYB. Por ejemplo, el opuesto del color rojo, debería ser el verde, pero en nuestro ejemplo es el cyan. ¿Podrías encontras la forma de igualarlo para que luzca igual a la siguiente imágen? [Pista: este es un buen momento para usar funciones de forma.]
![](colorwheel.png)
#### Nota acerca de las funciones y los argumentos
Antes de saltar al próximo capítulo, detengámosnos y retrocedamos. Volvamos a ver las funciones en los ejemplos previos. Notaras el ```in``` antes del tipo de argumento. Este es un [*qualifier*](http://www.shaderific.com/glsl-qualifiers/#inputqualifier) y en este caso indica que la variable es de solo lectura. En ejemplos futuros veremos que es posible definir argumentos como ```out``` o ```inout```. Este último, ```inout```, es conceptualmente similar a pasar un argumento por referencia, lo que nos da la posibilidad de modificar la variable pasada.
```glsl
int newFunction(in vec4 aVec4, // read-only
out vec3 aVec3, // write-only
inout int aInt); // read-write
```
Seguramente no me crees, pero ya tenemos todos los elementos necesarios para crear dibujos geniales. En el próximo capítulo aprenderemos a combinar todos nuestros trucos para crear formas geométricas *mezclando* el espacio. Si... *mezclando* el espacio.

@ -0,0 +1,94 @@
<canvas id="custom" class="canvas" data-fragment-url="examples/moon.frag" data-textures="examples/images/moon-texture.jpg" width="350px" height="350px"></canvas>
# The Book of Shaders
*por [Patricio Gonzalez Vivo](http://patriciogonzalezvivo.com/)*
Esta es una guía paso a paso a través del abstracto y complejo universo de los Fragment Shaders.
<div class="header">
<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=B5FSVSHGEATCG" style="float: right;"><img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif" alt=""></a>
</div>
## Contenidos
* [Acerca de este libro](00/)
* Comenzando
* [¿Qué es un shader?](01/)
* [“Hola Mundo!”](02/)
* [Uniforms](03/)
* [Ejecutando tu shader](04/)
* Dibujando con algoritmos
* [Funciones de forma](05/)
* [Colores](06/)
* [Formas](07/)
* [Matrices](08/)
* [Patrones](09/)
* Diseños generativos
* [Random](10/)
* [Noise](11/)
* Movimiento browniano
* Fractales
* Procesamiento de imágenes
* Texturas
* Operaciones de Imagen
* Convoluciones de Kernel
* Filtros
* Otros efectos
* Simulación
* Pingpong
* Conway
* Ripples
* Water color
* Reaction diffusion
* Gráficos 3D
* Luces
* Normal-maps
* Bump-maps
* Ray marching
* Environmental-maps (esféricas y cúbicas)
* Reflección y refracción
* [Apéndice:](appendix/) Otras formas de usar este libro
* [¿Cómo puedo ver el libro offline?](appendix/)
* [¿Cómo puedo correr los ejemplos en una RaspberryPi?](appendix/)
* [¿Cómo imprimir este libro?](appendix/)
* [Galería de ejemplos](examples/)
* [Glosario](glossary/)
## Acerca del autor
[Patricio Gonzalez Vivo](http://patriciogonzalezvivo.com/) (1982, Buenos Aires, Argentina) es un artista y desarrollador que actualmente reside en New York. Explora los espacios que convergen entre lo orgánico y lo sintético, lo analógico y lo digital, lo individual y lo colectivo. En su trabajo utiliza el código como un lenguaje expresivo con la intención de lograr algo superador.
Patricio estudió y ejerció psicoterapia y terapia de artes expresivas. Tiene un MFA en diseño y tecnología de la Parsons The New School, donde hoy da clases. Actualmente el trabaja como Graphic Engineer en Mapzen, creando herramientas open source para trabajar con mapas.
<div class="header"><a href="https://twitter.com/patriciogv" target="_blank">Twitter</a> - <a href="https://github.com/patriciogonzalezvivo" target="_blank">GitHub</a> - <a href="https://vimeo.com/patriciogv" target="_blank">Vimeo</a> - <a href="https://www.flickr.com/photos/106950246@N06/" target="_blank"> Flickr</a></div>
## Agradecimientos
Gracias a mi esposa [Jen Lowe](http://www.datatelling.com/), por su apoyo incondicional, su ayuda y el tiempo dedicado editando este libro.
Gracias a [Scott Murray](http://alignedleft.com/) por inspirarme y aconsejarme.
Gracias a [Kenichi Yoneda (Kynd)](https://twitter.com/kyndinfo) y a [Sawako](https://twitter.com/sawakohome) por la [Traducción al japonés (日本語訳).](?lan=jp)
Gracias a [Tong Li](https://www.facebook.com/tong.lee.9484) y a [Yi Zhang](https://www.facebook.com/archer.zetta?pnref=story)por la [Traducción al chino (中文版).](?lan=ch)
Gracias a [Jae Hyun Yoo](https://www.facebook.com/fkkcloud) por la [Traducción al coreano (한국어).](?lan=kr)
Gracias a [Karim Naaji](http://karim.naaji.fr/) por su contribución, su apoyo, su código y sus buenas ideas.
Gracias a todos los que creyeron en este proyecto y [contribuyeron con sus aportes](https://github.com/patriciogonzalezvivo/thebookofshaders/graphs/contributors) o donaciones.
## ¿Cómo conseguir los nuevos capítulos?
Suscribirse al newsletter o [seguirnos en Twitter](https://twitter.com/bookofshaders)
<form style="border:1px solid #ccc;padding:3px;text-align:center;" action="https://tinyletter.com/thebookofshaders" method="post" target="popupwindow" onsubmit="window.open('https://tinyletter.com/thebookofshaders', 'popupwindow', 'scrollbars=yes,width=800,height=600');return true"><a href="https://tinyletter.com/thebookofshaders"><p><label for="tlemail">Ingresa tu dirección de correo</label></p></a><p><input type="text" style="width:140px" name="email" id="tlemail" /></p><input type="hidden" value="1" name="embed"/><input type="submit" value="Suscribirse" /><p><a href="https://tinyletter.com" target="_blank"></a></p></form>
Loading…
Cancel
Save