# LA SHADER WIKI

Sitio colaborativo para la documentación y facilitación de material sobre programación creativa y escritura de shaders.

[Wiki ](https://es.wikipedia.org/wiki/Wiki)creada para fomentar la comunidad sobre shaders en español, registrar el material utilizado en distintos cursos y compartir recursos.


# INTRODUCTORIOS


# Live coding shaders por NODO Centro Cultral Digital


# Motivaciones

Reflexiones por Sol Sarratea que invitan a re-pensar nuestra relación con la tecnología, y animarse a tomar un curso sobre programación creativa.

## ¿Qué relación tenemos con las computadoras? <a href="#que-relacion-tenemos-con-las-computadoras" id="que-relacion-tenemos-con-las-computadoras"></a>

![](https://intro-shaders.solsarratea.world/images/ww.png)

> “En tanto que yo domine la herramienta, yo doy al mundo mi sentido; cuando la herramienta me domina, su estructura conforma e informa la representación que tengo de mí mismo. La herramienta convivencial es la que me deja la mayor latitud y el mayor poder para modificar el mundo en la medida de mi intención.”
>
> **La convivencialidad - Ivan Illich**

La diferencia entre las palabras, en el lenguaje natural, y el código puede pensarse como la diferencia entre contar y hacer. En estas clases vamos a experimentar a través de la creación de imágenes: fundamentos sobre programación; cómo comunicarnos con la GPU y aplicar conceptos matemáticos para generar arte.

Entende r las tecnologias de bajo nivel nos permite habitar nuevos espacios.

## Computadora, tecnología y arte en la historia: <a href="#computadora-tecnologia-y-arte-en-la-historia" id="computadora-tecnologia-y-arte-en-la-historia"></a>

#### ¿Cuáles son los orígenes de la computación gráfica? <a href="#cuales-son-los-origenes-de-la-computacion-grafica" id="cuales-son-los-origenes-de-la-computacion-grafica"></a>

![](https://intro-shaders.solsarratea.world/images/hombre.png)

#### ¿Qué sectores sociales tuvieron/tienen más privilegio? <a href="#que-sectores-sociales-tuvierontienen-mas-privilegio" id="que-sectores-sociales-tuvierontienen-mas-privilegio"></a>

> “Necesitamos regeneración, no resurrección, y las posibilidades que tenemos para nuestra reconstitución incluyen el sueño utópico de un mundo monstruoso sin géneros. **Manifiesto Cibor - Donna Haraway**”

Habitar nuevos espacios en tecnología nos permite regenerarnos. Y ser creadores de tecnología es posible en el contexto que vivimos.

### Referencias históricas de artistas pioneros <a href="#referencias-historicas-de-artistas-pioneros" id="referencias-historicas-de-artistas-pioneros"></a>

* [Lillian Schwart](https://www.google.com/search?client=firefox-b-d\&q=Lillian+Schwartz) [En la siguiente entrevista](https://vimeo.com/103817431) comparte reflexiones sobre la creatividad usando computadoras desdesde su experiencia.
* [Ken Knowlton](https://www.kenknowlton.com/), creador del lenguaje BELFIX. Desarrolló junto a Stan VanDarBeek una serie de peliculas tituladas [‘Poem Field](https://www.youtube.com/watch?v=V4agEv3Nkcs\&t=11s)’.
* [John Whitney](https://www.awn.com/mag/issue2.5/2.5pages/2.5moritzwhitney.html) pionero en animaciones. [Acá](https://www.youtube.com/watch?v=cP5Mj6ZvZJc) menciona varios aspectos de su vida y su trabajo. Y de las artes electronicas en el campo visual.

Para leer más, recomiendo [archivos de atari](https://www.atariarchives.org) y [este archivo de la historia](http://www.cs.cmu.edu/~ph/nyit/masson/history.htm) de la computación gráfica.

## Livecoding, comunidad y proyectos de código abierto <a href="#livecoding-comunidad-y-proyectos-de-codigo-abierto" id="livecoding-comunidad-y-proyectos-de-codigo-abierto"></a>

#### **El saber es una construcción social comunitaria.** <a href="#el-saber-es-una-construccion-social-comunitaria" id="el-saber-es-una-construccion-social-comunitaria"></a>

* [CliC: Colectivo de Live Coding](https://colectivo-de-livecoders.gitlab.io/)
* [Livecoding NYC](https://livecode.nyc/)
* [TOPLAP](https://toplap.org/)

#### **Repositorios de código : proyectos que se pueden ver, modificar, usar y distribuir** <a href="#repositorios-de-codigo-proyectos-que-se-pueden-ver-modificar-usar-y-distribuir" id="repositorios-de-codigo-proyectos-que-se-pueden-ver-modificar-usar-y-distribuir"></a>

* [Glitch.me](https://glitch.com/)
* [Github](https://github.com/)
* [Gitlab](https://about.gitlab.com/)
* [Sourcehut](https://sourcehut.org/)

> “El mero proceso de construcción es, por ende, entendido como un incansable, iterativo y continuo revestimiento. El Xenofeminismo busca ser una arquitectura mutable que, como el software de código abierto, se mantiene disponible a perpetua modificación y mejora siguiendo el impulso navegacional del razonamiento militante ético. Abierto, sin embargo, no significa sin dirigir. Los sistemas más durables en el mundo le deben su estabilidad a la manera en la que entrenamos al orden para emerger como una “mano invisible” de la espontaneidad aparente, o explotar la inercia de la inversión y la sedimentación. " **Paridad 0x10 - XF Manifiesto**


# Abril/Mayo 2022

Taller gratuito e intoductorio a la programación de shaders para generación de visuales dictado por Pilar Ledesma Gonzalez, Sol Sarratea y moderado por Daniela Mibashan

El mismo cuenta con dos partes.

* **Introducción a la programación creativa:**

Durante las clases se van a introducir nociones básicas de programación en Processing.

* **Introducción a shaders:**

Las clases están centradas en **la generación de imágenes visuales usando directamente la unidad de procesamiento gráfica (GPU).** Esto lo realizaremos a través de escribir un programa, shader, con GLSL (lenguaje de shading de openGL, una interfaz que nos habilita comunicarnos con el hardware gráfico).

Vamos a familiarizarnos con la sintáxis, similar a la de C. Y escribir el código a tiempo real (live codear) un shader usando glslEditor.\
**Objetivos:**

* Adquirir nociones básicas de GLSL.
* Entender las ventajas y desventajas de escribir programas que corran directamente sobre la GPU.
* Acercar al código creativo como práctica mundana.
* Crear, mostrar y participar.


# Estructura de cada CLASE

En cada clase se encuentran las slides de presentación de contenido.

Abajo una sección **PRÁCTICA** donde hay links a clases web modulares, que usan un glslEdior. Se ve así:

![](/files/Cw5XCX8IQ1PplZjBgvnm)

Y está pensado para seguir las clases virtuales con los checkpoints escuchando las explicacioens con la posibilidad de editar el código en la misma.

Para la práctica por fuera del taller, se sugiere partir de un checkpoint y editarlo en <http://editor.thebookofshaders.com/>.

Luego hay una sección **NOTAS,** con comentarios hechos en el transcurso de las clases.


# CLASE 28/04

Motivación y escritura del primer shader.

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vRh2vFfAYBz9lQwG5SFxfKJimI2Xh2Bar_P6oRaMafZgalWAVosuBquuz8wxQkgs9kCzYEzfGyyMXAY/pub?delayms=3000&loop=false&start=false>" %}

### PARTE PRÁCTICA

Restringimos a las funciones: cos(), step(), smoothstep(), length(), y mix().

En los siguientes links se encuentra el editor con checkpoints:

{% embed url="<https://clases-shaders.solsarratea.world/clases/fund0/editor>" %}
Sintaxis e introducción a ejes cartesianos
{% endembed %}

{% embed url="<https://clases-shaders.solsarratea.world/clases/fund1/editor>" %}
Dibujo de figura simple
{% endembed %}

### **NOTAS**

* GPU permite hace muchas operaciones en simultáneo. Esto implica que scribir programas que corran en la GPU permite que tengan mejor performance, y mayor complejidad.

{% embed url="<https://www.youtube.com/watch?v=-P28LKWTzrI>" %}
GPU vs CPU
{% endembed %}

{% embed url="<https://glitch.com/~shader-performance>" %}
App para testear el rendimiento de CPU vs GPU en frames
{% endembed %}

* **FRAGMENT SHADER:** entra posición sale color.

  * Declaración de **variables uniformes:** variables que contienen información "externa" que le programadore le puede pasr. Ejemplo: tiempo.
  * void () **main** {..}: cuerpo principal de ejecución.
  * **gl\_**{...}: son variables provistas para interacturar (leer y escribir información) en distintos momentos de la pipeline gráfica. Ejemplos:

    **gl\_FragCoord:** permite leer las coordenadas del píxel.

  **gl\_FragColor:** permite escribir el color que se va a renderear.


# CLASE 05/05

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vRepIE50imVIswL3MlZd_Yg5ziv6qBkc752I9B30msPXpnkrjGS9deD8866UoynZecu6miCyJl8LQlO/pub?delayms=3000&loop=false&start=false>" %}

### PARTE PRÁCTICA

En los siguientes links se encuentra el editor con checkpoints:

{% embed url="<https://clases-shaders.solsarratea.world/clases/fund2/editor>" %}

{% embed url="<https://clases-shaders.solsarratea.world/clases/formas/editor>" %}

### NOTAS

* [Funciones de distancia de signo:](/cursos/introductorios/live-coding-shaders-por-nodo-centro-cultral-digital/abril-mayo-2022/sdfs)
* Funciones Circulares : [3Demo](https://circular.solsarratea.world/)

Caracterizamos a las funciones sin() y cos(), como aquellas que describen el movimiento de caminar alrededor de un círculo.&#x20;

Para ello, imaginemos que en la 3Demo arrancamos "caminando" desde el punto azul hasta el magenta, y en cada paso intermedio nos detuvimos para registrar(sacar una foto de) esa posición. En total, tardamos `16 pasos` en recorrer el círculo. &#x20;

Imaginense, que además, por cada paso(registro/foto) podemos generar un circulo sólo con la posición registrada.

Arriba a la derecha, hay un slider `step` que nos permite visibilizar de manera independiente todas las veces que nos detuvimos. Es decir, visibilizamos ahora el el tiempo (cada anillo con un único registro).&#x20;

Y si movemos este tubo tridimensional con los respectivos ejes:

![Visibilizando la funcion sin(x)](/files/NuCRs6T3Vf3wfa7tBrOa)

![](/files/OyvQC2O6kzOoICe3Mkfi) ![](/files/UnRiEkaM4dz96B6LHSd9)

![Visibilizamos la función cos(x)](/files/1MI8huFcjp4RlxWdAUfa)

![](/files/HWFDv6BKBWs57ga5T0XJ) ![](/files/1KXYT8OwJOiSydqn9mOB)

En resumen, las funciones seno y coseno se las pueden pensar como las proyecciones (en los ejes  vertical y horizontal) de caminar en un círculo.&#x20;

* [Superfórmula](http://paulbourke.net/geometry/supershape/) : fórmula matemática que generaliza al Teorema de Pitágoras.\
  Se usa para describir curvas y formas en la naturaleza.

![](/files/nWlYmdk96wpVcPEaFlxs) ![](/files/BtNWdjpOe3Ukptxhez4S)

* [p-normas:](https://de.wikipedia.org/wiki/P-Norm) Vimos como dibujar un círculo con la función `length(pos)= pow(pow(pos.x,2.)+pow(pos.y,2.),1./2.) .`

  Es decir, usando la noción de distancia Euclídea. Vimos como generalizando la noción de distancia, cambiandio al `2` por **`p`** se generan otras figuras.

![Distintos valores de p](/files/Tjdx30DXcFZyjrkgMEm1)


# CLASE 12/05

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vQKzVKgVYEEOUVxbvkXGG6C0P2DPWU43nQvlioY_jl9jjQoCM5B-gYbfWg3gDkggVjpYmrsmaH7vD8v/pub?delayms=3000&loop=false&start=false>" %}
Repaso y transformaciones
{% endembed %}

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vSrajKqeS2KiIR1IO26pXCBtJ3EB4Y-KlqwAGfk670xg-vi9dL9uCLNPpNWgW1u8jbRkqGjPErg1Neb/pub?delayms=3000&loop=false&start=false>" %}

**PRÁCTICA**

En el siguiente link se encuentra el editor con checkpoints:

{% embed url="<https://clases-shaders.solsarratea.world/clases/trnsf/editor>" %}

**NOTAS**

**BONUS - Fin de Curso**

![](/files/RV7xxHlGugIK4xdXfWNR)

```
// Author: Sol Sarratea @solquemal
//Title: BONUS - Raymarching
precision mediump float;
uniform float u_time;
uniform vec2 u_resolution;

vec2 uv(){
  /* Devuelve las posiciones del canvas en rango [-1.,1.]x[-1.,1.] */
  vec2 pos = gl_FragCoord.xy/u_resolution; 
  pos.x *= u_resolution.y/u_resolution.x;
  pos = pos *2.-1.;
  return pos;
}

void main() {
    vec3 pos = vec3(uv(),1.);
   
    vec3 cam = vec3(0.,3., -9.);
    cam.z +=u_time;
    vec3 rayo = normalize(pos); 
    
    float marcha = 0.;
    for(int i=0; i < 32; ++i){
        vec3 p = cam + rayo * marcha;
        float d = length(sin(p)+cos(p.yzx))-.5;
        marcha += d;
        if (marcha > 50. || d < 0.01) break; 
     }
    
    vec3 color;
    color += pow(0.908,marcha);
	
    gl_FragColor = vec4(color, 1.);

}


```

***


# SDFs

Conjutno de funciones para dibujar figuras simples

Extraidas de:

{% embed url="<https://iquilezles.org/articles/distfunctions2d>" %}

* Círculo:

```
float sdCircle( vec2 p, float r ) { 
    /* Devuelve la distancia al circulo de radio r */
    return length(p) - r; 
}
```

* Cuadrado:

```
float sdBox( in vec2 p, in vec2 b )
{  /* Devuelve la distancia al cuadrado de lados b */

    vec2 d = abs(p)-b;
    return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
}
```

Ejemplo de uso:\
\
`color += smoothstep(0.01,0.0,sdBox(pos, vec2(.3)));`

* Triángulo equilátero:

```
(https://www.shadertoy.com/view/Xl2yDW)
float sdEquilateralTriangle( in vec2 p )
{
    const float k = sqrt(3.0);
    p.x = abs(p.x) - 1.0;
    p.y = p.y + 1.0/k;
    if( p.x+k*p.y>0.0 ) p = vec2(p.x-k*p.y,-k*p.x-p.y)/2.0;
    p.x -= clamp( p.x, -2.0, 0.0 );
    return -length(p)*sign(p.y);
}
```


# Lista de funciones

Lista completa de funciones:

* <https://www.shaderific.com/glsl-functions>
* <https://thebookofshaders.com/glossary/>

\
FUNCIONES\
Trigonometría

* cos(x)
* -sin(x)
* tan(x)

\
Potencia

* pow(x, 0.5) == sqrt(x)
* pow(x, 1.)
* pow(x, 2.)
* pow(x, n) para cualquier n:=número
* sqrt(x): raiz cuadrada
* inversesqrt(x) 1./sqrt(x)\
  \\

Exponenciales

* exp(x) : base 10
* exp2(x): base 2

\
Logaritmos

* log(x) : base 10
* log2(x) : base 2

\
Geometría

* length(x): longitud de un vector en la norma euclideana.
* distance(x,y): distancia entre x e y
* dot(x,y): producto interno entre x e y (producto escalar)\\

Otras

* abs(x) : valor absoluto de x. Ej. abs(1)=1, abs(-1)=1
* sign(x) : signo de x. Ej sign(1)=1 sign(-1)=0
* floor(x) : el numero entero más cercano que es menor a x. Ejempl: floor(3.14) = 3
* ceiling(x):el numero entero más cercano que es mayor a x. Ejemplo: ceiling(3.14) = 4
* fract(x): la parte fraccional de x. Ejmplo: fract(3.14)= .14;
* min(a,b): minimo valor entre a y b
* max(a,b): minimo valor entre a y b
* clamp(x, a, b): si \`x\` es menor a \`a\` devuelve a, si \`x\` es mayor a \`b\` devuelve \`b\`, sino devuelve \`x\`.
* mod(x, y): devuelve el resto de la division de "x dividido y"
* mix(x, y, a): x\*(1.-a)+y\*a
* step(x, a): devuelve 0 si x <= a, y devuelve 1 si x > a.
* smoothstep(x,a,b): devuelve 0 si x\<a, interpola linalmente entre 0 y 1 si a\<x<=b, devuelve 1 si x > b\\

Ejemplo para usar en explorador de funciones:

`float y = cos(pow(cos(x*x+u_time*.1),1.5)*10.-u_time);`\
\
\
\
\
\
\
\
\
\
\\


# Agosto/Septiembre 2021

Taller gratuito e intoductorio a la programación de shaders para generación de visuales dictado por  Sol Sarratea y moderado por Daniela Mibashan

El curso originalmente fue hosteado en el link de abajo:

{% embed url="<https://intro-shaders.solsarratea.world/clases/>" %}

Para complementar con contenido teórico, recomiendo acceder [al curso dictado en 2022](/cursos/introductorios/live-coding-shaders-por-nodo-centro-cultral-digital/abril-mayo-2022).

Quienes de todas maneras le interesan simplemente los checkpoints de las clases:

## Clase 00

{% embed url="<https://intro-shaders.solsarratea.world/clases/clase0/editor/>" %}

## Clase 01

{% embed url="<https://intro-shaders.solsarratea.world/clases/clase1/editor/>" %}

## Clase 02

{% embed url="<https://intro-shaders.solsarratea.world/clases/clase2/editor/>" %}


# Sobre nosotres

### NODO Centro Cultural Digital <a href="#nodo-centro-cultural-digital" id="nodo-centro-cultural-digital"></a>

![](https://intro-shaders.solsarratea.world/images/nodo.png)

NODO abre sus puertas, si es que tuviesemos puertas. Somos un centro cultural común y corriente, pero enteramente digital. Un punto de encuentro para pensar las artes en su especificidad virtual. Una usina de pensamiento en una sociedad cada vez más virtualizada. Una plataforma de exhibición, creación y vinculación en busca de democratizar las culturas digitales. Ah, y atrás de algoritmos y líneas de código, un grupo de jóvenes que busca construir una digitalidad plural y accesible.


# TEMÁTICOS


# Computando visiones del CAOS en GLSL por CCEBA Media Lab

Sistemas Dinámicos, Fractales, Efecto Mariposa y más.

El contenido de esta sección se desarolló para el curso remoto del CCEBA Media Lab, con el fin de documentar y facilitar el contenido del mismo.

{% embed url="<https://caos.solsarratea.world/images/demo.gif>" %}


# Clases

Descripción sobre la estructura del curso y de cada clase.

## Sobre el curso: <a href="#sobre-el-curso" id="sobre-el-curso"></a>

Lo que no es:

* curso introductorio a fundamentos de GLSL.
* curso de matemática-física avanzada.

El curso busca:

* Explorar ideas distintas, y combinarlas con creatividad.
* Los shaders como medio para computar ideas.
* La computadora como herramienta convivial.
* Crear una comunidad de aprendizaje.

Fusionar arte y ciencia en el imaginario creativo.

## **Sobre las clases:** <a href="#sobre-las-clases" id="sobre-las-clases"></a>

Si bien introduciremos muchos conceptos nuevos en términos de programación y matemática. Para no perder el rumbo, nuestra brújula en este curso será el término ITERACIÓN. A partir del mismo, vamos a estar estudiando durante la primera semana sobre Fractales, y durante la segunda nos focalizaremos en Sistemas Dinámicos.

El contenido de las clases quedará en esta web disponible para consultar.Además, todo el contenido está pensado de manera modular, para poder adaptarse a las dinámicas y necesidades del grupo. \[\*] y se puede acceder​ <https://caos.solsarratea.world/rumbo/>.


# Clase 0

## SCHEDULE

| Hora           | Bloque                                                            |
| -------------- | ----------------------------------------------------------------- |
| 15.00 - 16.00  | <p>Presentación del curso</p><p>Intro a lenguajes de shading</p>  |
| 16.10 - 16. 50 | Módulo práctico: Fundamentos sobre GLSL                           |
| 17.00 - 18.00  | <p>Intro al concepto de Iteración</p><p>Módulo práctico: IFSs</p> |

## Introducción a lenguajes de shading

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vR57Gj-FdPYtIRIcf4UgXNO_9-aYuoH88zqhNVp9W_qQds7iCC8flv3ax78XmNuRMSepyLanrNM1Hak/pub?delayms=3000&loop=false&start=false>" %}

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vS1mKPjAkkHIaO2gCJC_-RmdbzkXiTyH1W3_Oan87AWoK0EE9LDLjQooIU8nKQ5LO8H6iggA3P3fiuz/pub?delayms=3000&loop=false&slide=id.g84efe72288_0_30&start=false>" %}

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vSrajKqeS2KiIR1IO26pXCBtJ3EB4Y-KlqwAGfk670xg-vi9dL9uCLNPpNWgW1u8jbRkqGjPErg1Neb/pub?delayms=3000&loop=false&start=false>" %}

#### PRÁCTICA

{% embed url="<https://caos.solsarratea.world/rumbo/fund/editor/>" %}
IR A LA ACTIVIDAD PRACTICA 0
{% endembed %}

{% embed url="<https://caos.solsarratea.world/rumbo/ifs/editor/>" %}
IR A LA ACTIVIDAD PRACTICA 1
{% endembed %}

#### FEEDBACK

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vR1yL1uFfoBBaSOkXt9uN0dlmim_4NDOF6yBnSP5TC8ZaN0Rdp0KByUGo2X6dk5WTdNx_hc7ql71OjA/pub?delayms=3000&loop=false&start=false>" %}
Introducimos métrica John Travolta para cuantificar el nivel de entendimiento
{% endembed %}


# Clase 1

##

## SCHEDULE

| Hora           | Bloque                                                                            |
| -------------- | --------------------------------------------------------------------------------- |
| 15.00 - 15.45  | Más sobre IFSs, y curva de Koch.                                                  |
| 15.45 - 16. 00 | Tiempo Creativo                                                                   |
| 16.00 - 16.40  | Definimos fractales, y aprendemos a medirlos.                                     |
| 16.50 - 17.30  | Fractales en dominio Complejo: Conjuntos de Julia, Mandelbrot y Fractal de Newton |
| 17.30 - 18.00  | Tiempo Creativo                                                                   |

**CONTENIDO TEÓRICO**

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vQeCvKpLRhm9RJo_J_z_IJsMtItXH46O5j6HZAwJikWr8vi4htPP72hiGUpMQdt4uRVk-hXNoiYM4kk/pub?delayms=3000&loop=false&start=false>" %}

{% embed url="<https://docs.google.com/presentation/d/1qR2wMKQ2ibTrRfB_5xiQYi4-TyMHkj38ygaO_AMDo0k/edit?usp=sharing>" %}

{% embed url="<https://acko.net/blog/how-to-fold-a-julia-fractal>" %}

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vSA2ox7de-YcISSYmArmskyzqtSwmQheMyvPykeA9IK9L3Aaa8dwmxZec3d3Qgbgqg4UJSODiuPuAtj/pub?delayms=3000&loop=false&start=false>" %}

#### PRÁCTICA

{% embed url="<https://caos.solsarratea.world/rumbo/koch/editor/>" %}

{% embed url="<https://caos.solsarratea.world/rumbo/julia/editor/>" %}

{% embed url="<https://caos.solsarratea.world/rumbo/mandelbrot/editor/>" %}

{% embed url="<https://caos.solsarratea.world/rumbo/newton/editor/>" %}

#### ARTE Y FRACTALES

{% embed url="<http://dpya.org/wiki/index.php/1999_-_The_Fractal_Art_Manifesto_-_Kerry_Mitchell>" %}

{% embed url="<https://www.kerrymitchellart.com>" %}

{% embed url="<https://www.fractalus.com/ifl>" %}
WebRing de Arte Fractal
{% endembed %}

{% embed url="<https://users.math.yale.edu/public_html/People/frame/Fractals/Panorama/Literature/IntFracLit/IntFracLit.html>" %}

{% embed url="<http://www.abm-enterprises.net/wallpaper.html>" %}


# Clase 2

## SCHEDULE

| Hora          | Bloque                               |
| ------------- | ------------------------------------ |
| 15.00 - 15.45 | Fractales 3                          |
| 15.45 - 16.15 | Tiempo Creativo                      |
| 16.15 -15.50  | Intro a sistemas dinámicos           |
| 16.50 - 17.00 | PAUSA                                |
| 17.00 - 17.20 | Intro a sistemas dinámicos: péndulos |
| 17.20 - 18.00 | Tiempo creativo                      |

**CONTENIDO TEÓRICO**

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vQwKXSRFbj89S7j5g3k0MAa_Sj-evFlxL_OZxvnuye5IMz3tCMDZaCPHKItyClKAg1Yfx2oJ4Ejr1JI/pub?delayms=3000&loop=false&start=false>" %}

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vSXZU_DsuTXWtUxj7KQNXwCixKdvgtrHXdZmIkVLchGhRNS8hiizL7VGcO-d_wYWKDz5xccqdKf524o/pub?delayms=3000&loop=false&start=false>" %}

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vSbbOwCH5_ISqEWep0kMC-Dzd991LVO1aHpEf7siJl-Tj3xDXZJ7YSOOpAVv0qxivnZrEzx-5XfbzwS/pub?delayms=3000&loop=false&start=false>" %}

**CONTENIDO PRÁCTICO**

{% embed url="<https://caos.solsarratea.world/rumbo/mandelbrot/editor/>" %}

{% embed url="<https://colab.research.google.com/drive/1_XtB4sfpgZGomogUef9N5IeV47Hqyezs?usp=sharing>" %}

{% embed url="<https://caos.solsarratea.world/rumbo/logistic/editor/>" %}

{% embed url="<https://caos.solsarratea.world/rumbo/pendulos/editor/>" %}


# Clase 3

## SCHEDULE

|                | Bloque                                 |
| -------------- | -------------------------------------- |
| 15.00 - 15.45  | iteración, bifurcación y universalidad |
| 15.45 - 16.50  | Orbitas + Tiempo Creativo              |
| 17.00 - 17. 10 | Sistemas Dinamicos                     |
| 17.10 - 17.50  | Atractores + Tiempo Creativo           |
| 17.00 - 18.00  | Fin de Curso                           |

**CONTENIDO TEÓRICO**

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vSAlWcUJzUADLMaEcpQj_Ew2NTnEB6n0w_Pp8ioB3_W9MVz5eILlJwbWiJSkX_vGWdPOhonMNg4Ge-D/pub?delayms=3000&loop=false&start=false>" %}

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vSo3ovbyRWgFuXCczPz-6Ma-dA2il5jPHRnecel50MgilU4aZ373Tn0ZvlwhI4jeDiyNpIXYaS7-B50/pub?delayms=3000&loop=false&start=false>" %}

**CONTENIDO PRÁCTICO**

{% embed url="<https://caos.solsarratea.world/rumbo/orbits/editor/>" %}

{% embed url="<https://caos.solsarratea.world/rumbo/atractors/editor/>" %}


# Material de consulta y referencia

## GLSL

{% embed url="<https://thebookofshaders.com>" %}

{% embed url="<https://iquilezles.org>" %}

{% embed url="<https://curso.solquemal.com>" %}
Curso introductorio
{% endembed %}

### Intuición sobre funciones y matemática

{% embed url="<https://www.dsprelated.com/showarticle/754.php>" %}

{% embed url="<https://betterexplained.com/archives>" %}

{% embed url="<https://curso.solquemal.com/herramientas/ninja0>" %}

## CAOS

Agradecimiento a todas las personas que aportaron a la creacioón de este contenido web.

#### Inspiraciones

{% embed url="<https://softology.com.au/voc.htm>" %}

{% embed url="<https://blog.rotgers.io>" %}

{% embed url="<https://www.cs.unm.edu/~joel/WebGL>" %}

### Artículos técnicos y experimentos digitales

{% embed url="<https://spaceandtim.es/etc/chaos_and_reductionism>" %}

{% embed url="<http://www.tnellen.com/ted/tc/complexity.html>" %}

#### Fractales

{% embed url="<https://solquemal.com/garden/fractals>" %}

{% embed url="<http://paulbourke.net/fractals>" %}

{% embed url="<https://fractalfoundation.org/OFC>" %}

{% embed url="<https://www.karlsims.com/julia.html>" %}

#### Caos

{% embed url="<https://hypertextbook.com/chaos/logistic>" %}

### Artículos sobre naturaleza y experimentos en el mundo físico

{% embed url="<http://ullagami.com/how-to.php>" %}
✂️📐
{% endembed %}

{% embed url="<http://paulbourke.net/fractals/leaves>" %}
🍁 🍂 🍃
{% endembed %}

{% embed url="<http://paulbourke.net/fractals/googleearth>" %}
🌎
{% endembed %}

{% embed url="<http://www.ace.gatech.edu/experiments2/2413/lorenz/fall02>" %}
💦 🔈
{% endembed %}

{% embed url="<https://botanicamathematica.wordpress.com/2013/03/18/chaotic-knitting>" %}
tejer 💜
{% endembed %}

{% embed url="<https://www.karlsims.com/harmonograph>" %}
harmonograph ❤️
{% endembed %}

{% embed url="<https://www.instructables.com/Visualizing-Chaos-With-the-Double-Pendulum>" %}
Doble Péndulo
{% endembed %}

### Hyperlinks: link con links

{% embed url="<https://web.archive.org/web/20000829113446/http://thasos.cc.duth.gr/~mboudour/nonlin.html>" %}


# Notas sobre referencias bibliográficas

Para consultar las fuentes originales mandarme un email a `solquemal [a] gmail.com`

La mayoría están en inglés.


# Metamagical Themas: Questing for the Essence of Mind and Pattern by Douglas R. Hofstadter

Douglas introduce cuatro ideas matemáticas como portal a estructuras matemáticas: El cubo mágico; Orden y Caos, explicando los atractores extraños; Recursión y recursividad, mediante el lenguaje de programación LISP; fenómenos quantum y las misteriosas relaciones no resueltas entre micro-macro mundos.

### ORDEN Y CAOS

#### Matemática experimental

La computadora digital cumple el rol del barco de Magallanes, el telescopio de los astrónomos, el acelerador de partículas de los físicos. Y así como barcos, telescopios, aceleradores son cada vez mas grandes y costosos, menciona que para poder explorar regiones desconocidas del espacio matemático se necesitan computadoras aún más grandes, más rápidas, con mayor precisión.

*Lo cual, personalmente, no estoy de acuerdo. Pero me gusta la idea, de **usar la computadora digital como el medio para explorar regiones desconocidas del espacio matemático.** Y creo que mientras más personas estén comprometidas en este uso, el co-crear habilitará regiones inexploradas.*

Además, habla como el **hacer matemática** de esta manera construye un imaginario visual e intuiciones en nuestro propio entendimiento. El poder de las computadoras de permitir crear una alternativa a modelos tradicionales de¨teorema-demostración-teorema-demostración¨, y alcanzar observaciones empíricas y descubrimientos que se refuerzan mutuamente.

Creando una red de resultados de tremenda riqueza. De todas maneras, esta sería una manera de ganar intuición para luego relizar demostraciones, en caso de ser necesario. Es decir, no es un reemplazo de los modelos tradicionales, sino un complemento.

#### Feedback de audio

La idea básica se puede extraer en los conocidos ciclos de retroalimentación (*feedback loops*). Es decir, expresiones cuya valor de salida (output) se convierte en la entrada (input) de la misma.

Para ejemplificarlo, usa un parlante conectado un micrófono. En donde, la señal que recibe el micrófono se amplifica mediante el parlante. El sonido que emite el parlante es capturado por el micrófono. Y se repite el loop.

Mas allá de la explicación, suena así (y es probable que varies lo hayamos experimentado en algún recital).

{% embed url="<https://soundcloud.com/breathingspace/feedback-sound>" %}

Mediante este ejemplo, Douglas menciona cómo es posible observar distintos patrones estables y caóticos sensibles a pequeños cambios. Describiendo una perfecta imagen de como el orden se sumerge en el caos de manera gradual; de como los patrones se disuelven gradualmente en lo que parece random.

En este contexto, menciona la importancia de sistemas caóticos para revelar aspectos sustanciales en fenómenos físicos \*\*no-lineares, **como la Turbulencia**. \*\*Es decir, dadas dos soluciones a las ecuaciones de turbulencia al sumarlas (hacer una combinación lineal de las mismas) no necesariamente es una solución.


# Caos by James Gleick

### Prólogo

Describe al Caos a partir de distintas ciencias, motivando como es una ciencia que estudia la \*\*naturaleza de los sistemas. \*\* Es decir, entender los modelos físicos desde un punto de vista cualitativo y no meramente cuantitativo.

Menciona que las tres cosas que revolucionaron la ciencia física del siglo XX fueron:

* Relatividad: eliminó la ilusión Newtonianan de considerar al tiempo y espacio absolutos
* Teoría Cuántica: eliminó el sueño Newtoniano de tener procesos de medición controlables
* Caos: eliminó la fantasía de Laplace de predectibilidad determinística

Además menciona como el Caos habilitó\*\* el uso de las computadoras \*\*con distintas técnicas y generación de imágenes que \*\*lograban capturar \*\*la fantástica y delicada **estructura** de lo aparentemente complejo.

Para algunos físicos el caos es la ciencia de **procesos en vez de estados**, de **convertirse en vez de ser.**

Menciona como tradicionalmente cuando los físicos veían resultados complejos, buscaban por causas complejas. Cuando encontraban una relación random entre las cosas que entraban a un sistema y su salida, creían que era cuestión de formalizar ¨lo random¨ dentro de una teoría realística, agregando ruido o un error.

El estudio moderno del Caos empezó cuando en 1960s ecuaciones matemáticas simples podían modelar sistemas drásticamente distintos. Como las pequeñas diferencias en los input podrían conllevar rápidamente en grandes deiferencias en el output, a este fenómeno se lo llamó ¨sensible dependencia en condiciones iniciales¨ \*\* \*\*


# The Fractal Geometry of Nature by Benoit Mandelbrot

La geometría euclideana deja de lado las figuras "sin forma" que encontramos normalmente en la naturaleza, por ejemplo en las nubes y en las costas limiítrofes. Motivado por la existencia de estos patrones existentes, la **geometría fractal busca modelar estos patrones irregulares y fragmentados.**


# Adicional: Noviembre 2022 -  Grupo, presentaciones y generación de personajes

Rescatando data de  Google Forms.

El recurso de introducir contenido teórico mediante historias suele ser un recurso muy usado cuando somos niñes, que luego se deja de usar. Como en este curso venimos de contextos distintos, es necesario hacer analogías y entender que espera cada une de las clases así las mismas van a ser funcionales.

Para ello hubo una invitación a elegir su rol, en una nave, la cual iba a ser liderada por quien dictaba las clases.

![El formulario se veia así y contaba con una serie de preguntas.](/files/qum3JVTH6Mv4TsZthHiy)

## Roles :

`"Percibo mi rol como el de los musicos en el titanic, todo era caos pero la orquesta tenia que seguir tocando para dar un poco de esperanza, bueno un poco todo en mi cabeza es caos a nivel de entendimiento, pero muy esperanzada y con ganas de ponerle onda"`

`"el ChePibe que está en alguna parte de la nave haciendo algo, sin entender muy bien qué está haciendo, pero poniéndole onda"`

`"El que mira por el periscopio, siempre atento a las infinitas maravillas cosmicas que este curso nos traera <3"`

`"Gilligan, de la Isla de Gilligan. Soy un marinero torpe en el mar del código, pero le meto garra."`

`"el que dispara el láser, porque al parecer se divierten y al mismo tiempo defienden la nave"`

`"Observadxr tímidx - Tal vez mi mayor intención es pasar a otro rol. Por hoy solo este."`

`"Terapeuta de la nave si alguien necesita hablar de sus frustraciones con shaders."`

`"Intrusa que no entiende el lenguaje pero que algo le hace quedarse"`

`"Encontré "Especialista de misión" y me pareció un rol genial"`

`"Tripulante Habitue que aun no se familiariza con la nave x_X"`

`"Pasajero con un par de horas de vuelo y mucha curiosidad"`

`"Fotografo. Lo que se ve por laventana no se me escapará"`

`"El encargado de proveer los equipos de hardware"`

`"Pasajero dispuesto a ayudar en lo que surja el que anima a realizar las ideas locas"`

`"cuidar las plantitas que esten a bordo"`

`"El compositor de la capilla real"`

`"Oficial Radioelectrónico y DJ" "compilador de links y data"`

`"La que lleva la bitácora" "Turista intergaláctico"`

`"Bartender turisteando" "Ingeniero de a bordo"`

`"naturalista viajera" "Ingeniero de vuelo" "Escuchadora malabarista"`

`"observador" "Navegacion"`

`"Poeta niña" "Explorador"`

`"El Rookie" "Marinero" "Copiloto"`

## Imágenes aportadas por personajes:

![](/files/CoTgiPRlaxXowNIw5G0b)![](/files/0gRluoxr6QSOn403eDhn)![](/files/DAHqP4Q5MyopWf3Z6Nnv)![](/files/qCWS3li6BhZzVilxJHcU)


# Quienes somos

## Facilitado por CCEBA Media Lab

El **CCEBA Centro Cultural de España en Buenos Aires** forma parte de la Red de Centros de Cooperación Cultural de la Agencia Española de Cooperación Internacional para el Desarrollo (AECID).

[Más info](http://www.cceba.org.ar/quienes-somos-2)

## Sol Sarratea

Es de Buenos Aires Argentina, estudiante de la facultad de Ciencias Exactas-UBA; desarrolladora en computación gráfica y artista computacional. Le apasiona construir sistemas complejos a partir de componer procesos simples, usando tecnologías de bajo nivel.

Es miembro de CliC; Colectivo de Live Coders. Sus proyectos son alentados por comunidades de código abierto; aprendizaje alternativo; y por la necesidad de construir una identidad propia.\
Participó en el Recurse Center - Nueva York; y en la academia de verano de Hackers\&Designers - Holanda. Lideró el curso sobre `Alquimia Digital` en Hyperlink Academy. Asistió y dictó workshops introductorios a GLSL en inglés y en español: en CODAME; WIP:Arte Digital; y NODO: Centro Cultural Digital.

Recientemente:

![Proyecciones en el Faro de Glommen, Suecia](/files/VFXMUMTgvwV5ivyTihfL) ![Colaboración en instalacion audiovisual en el Festival de Luces de Uppsala, Suecia](/files/p16EdBivgS6woy1CVJ5E)

A continuación mis cartas de presentación:

<div align="center"><img src="/files/1yMZRN0lRN9yBL1VXs1r" alt=" Llibros que cambiaron mi relación con las computadoras acompañados de imágenes que fueron generadas a partir de simples sistemas de feedback con el fin de entender luz y simular metales."> <img src="/files/sckMsfAu0Bw5isfMYM91" alt="Antigua slide de presentación"></div>

&#x20;


# Blobniverso: creación de universo moldeable a través del livecoding

Introducción  a la técnica de ray marching a través del livecoding.

\
El contenido de esta sección se desarrolló para el  curso gestionado **por TELRAGNA**  en el marco de **Talleres de experimentación y creación artística .**<br>


# Sobre el taller

El curso busca:

* Explorar ideas distintas, y combinarlas con creatividad.
* Los shaders como medio para computar ideas.
* La computadora como herramienta convivial.
* Crear una comunidad de aprendizaje.
* Expandir el imaginario creativo.
* Divertirse :D

Tendremos principalmente dos bloques:

* Introducir shaders y crear un ray marching simple.
* Agregar controles de color y movimientos de cámara.


# Quienes somos

## Facilitado por TELRAGNA

[Telaraña](https://www.instagram.com/telaragna_/) es responsable del comisariado y dirección del ciclo: **Talleres de experimentación y creación artística**, apostando por la diversidad y la investigación. El arte se presenta aquí como una herramienta para pensar, sentir y transformar, creando un espacio de formación que conecta la educación no formal con la producción artística y la sociedad.<br>

## Sol Sarratea

Es programadora | artista | entusiasta de la teoría y los métodos formales en matemáticas e informática. Es de Argentina, pero actualmente vive en Alemania. Escribe *software* desde 2018, con un ritmo muy intenso de aprender y hacer. Desde hace un par de años viaja y trabaja como *freelance*.&#x20;

Como *live coder* (o *performer*) comparte su pantalla, código, herramientas, y dirige talleres sobre las técnicas implicadas. Prioriza el uso de herramientas de código abierto y aboga por la libertad de acceso al conocimiento.&#x20;

<figure><img src="/files/SiC268lFIZaJNTzKb2mI" alt="" width="375"><figcaption><p>Cute Goblins</p></figcaption></figure>

&#x20;


# Herramientas

Esta wiki :D

Bajo la sección **Contenido,** están las áreas que esperamos cubrir durante la duración del taller.&#x20;

## Para la generación de visuales <a href="#sobre-las-clases" id="sobre-las-clases"></a>

Usaremos una versión customizada del editor online de shader [The\_Force](https://shawnlawson.github.io/The_Force/) creado por [Shawn Lawson](https://www.shawnlawson.com/)  <3

[Código fuende - versión original](https://github.com/shawnlawson/The_Force)

[Ver código fuente](https://github.com/solsarratea/The_Force/tree/blobniverse)[ - Fork de Sol Sarratea, Branch: Blobniverse](https://github.com/solsarratea/The_Force/tree/blobniverse)


# Código de conducta

Es muy importante crear un espacio seguro entre todes 🌈

## Código de conducta : Clases

### ¡Bienvenides!

Buscamos que durante las clases este sea un espacio de contención, de respeto y libre de acoso para todes En fin de poder crear un ambiente distendido, de aprendizaje y seguro.

Actualmente organizamos:

* [Sol Sarratea](mailto:ssarratea@mailbox.org?subject=%5BGitHub%5D%20Source%20Han%20Sans)
* TELARAGNA

### Comportamientos no aceptables

Incluyen:

* Comentarios ofensivos, como por ejemplo, aquellos relacionados con el género, identidad de género, expresión de género, orientación sexual, capacidades físicas, salud mental, apariencia física, etnia o religión.
* Comentarios no deseados sobre las prácticas o elecciones de estilo de vida de una persona, incluyendo aquellos relacionados con alimentación, salud, trabajo, crianza o uso de drogas.
* Uso intencional e incorrecto de los pronombres elegidos o utilización del ‘dead name’1 al referirse a una persona.
* Imágenes o comportamientos sexuales no solicitados, tanto virtuales como presenciales.
* Amenazas.
* Intimidación intencional.
* Atención sexual no solicitada.
* Comunicación privada que no cesa cuando se solicita.
* Publicaciones de comunicaciones privadas que no califican como acoso.

El ‘dead name’ es aquel nombre que se le asignó a una persona al nacer y ya no lo utiliza más.

### Denuncias y consultas

Si te están acosando, notás que otra persona está siendo acosada, ves algún comportamiento no aceptable o tenés cualquier otra inquietud, por favor contactate. Es necesario, y la responsabalidad de todes de garantizar los espacios seguros.

Respetaremos los pedidos de confidencialidad para proteger a las víctimas de acoso.

### Consecuencias

Toda persona a quien se le haya pedido que detenga su comportamiento debe hacerlo inmediatamente.

Si alguien se comporta de manera abusiva o violenta, se le restringira el acceso al resto de las clases e identificándole públicamente como alguien de quien recibieron quejas.

### Créditos y Licencia

Este código de conducta está basado en el [Código de conducta de \[LAS\] de Sistemas ](https://github.com/lasdesistemas/codigo-de-conducta); en el [Sample Slack Code of Conduct](https://gist.github.com/annalee/2cddeff11357c3a8a613583ebca4dc17) de Annalee Flower Horne, el cual a su vez se basa en la [Community Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Community_anti-harassment/Policy).

[view raw](https://gist.github.com/solsarratea/1409b0afe055a29e6aaa1e8e9c55d9d8/raw/f203ae61ab9007ee12a16ec8f355003b8fd31f67/clases-coc.md)[clases-coc.md ](https://gist.github.com/solsarratea/1409b0afe055a29e6aaa1e8e9c55d9d8#file-clases-coc-md)hosted with ❤ by [GitHub](https://github.com/)


# Contenido

Si bien habrá mucho contentido sintáctico y teórico sobre shaders..

<figure><img src="/files/OAjrIlUPFn4QA0Q39HAq" alt=""><figcaption></figcaption></figure>

El objetivo es poder combinar los scripts vistos, entender donde modificar valores numéricos, dibujar en un canvas y crear mundos personalizados :)\
Es decir, no esperamos que escriban *shaders from scratch* pero si que..<br>

<figure><img src="/files/twG8jXlGF8iFuRUvVPp8" alt=""><figcaption><p>demo</p></figcaption></figure>

aprendan, crean cosas  y se diviertan :)


# Presentación

## Slides<br>

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vQssacrlbaMyUMp7vTDZ4IMln7wHRosizPzf__1n5QbCa4vSEzrtkyf06wOPp6OeihCvt-LF8fEQaTT/pub?delayms=3000&loop=false&start=false>" %}

### Notas

GPU permite hace muchas operaciones en simultáneo. Esto implica que escribir programas que corran en la GPU permite que tengan mejor performance, y mayor complejidad.

{% embed url="<https://shader-performance.glitch.me/>" %}
LoadPixels vs shader
{% endembed %}

{% embed url="<https://www.youtube.com/watch?v=-P28LKWTzrI>" %}
GPU vs CPU
{% endembed %}

## Presentación de The\_Force

Es un editor web de GLSL, que compila el código a medida que lo escribamos. A continuación las secciones que empiecen con la palabra **Script:** son para que puedan copiar y pegar el código en el editor online.

Vamos a usar una versión local para ello conectarse a: \
\- red: Myfi\
\- pass: makelovenotwar

[Descargarse el contenido de las clases offline](https://drive.google.com/file/d/1SeJtJrSNY5tiKeHzMwGd7OdiL8Dh58WK/view)

<figure><img src="/files/IQH6AYOTBpfUVxFJEiBo" alt=""><figcaption><p>Versión Remix de The Force</p></figcaption></figure>

## Script: sintaxis básica de un shader

```glsl
void main() {
    /* Declaracion de variables
       tipo nombre = valor; */

    // Numeros reales
    float numero_0 = 1.0;
    int numero_1 = 1;

    // Vectores 
    // 2 dimensiones [_ ,_ ]
    vec2 v2_0 = vec2(0.,1.);
    vec2 v2_1 = vec2(numero_0,numero_1);

    //3 dimensiones [_ ,_ ,_ ]
    vec3 v3_0 = vec3(0.,0.5,1.);
    vec3 v3_1 = vec3(v2_0,1.);
    vec3 v3_2 = vec3(v2_0,numero_0);

    //4 dimensiones [_ ,_ ,_ ,_ ]
    vec4 v4_0 = vec4(0.,0.25,0.5,1.);
    vec4 v4_1 = vec4(v2_0,v2_1);
    vec4 v4_2 = vec4(v3_0,0.);

    // Acceso a los vectores
    // [r, g, b, a] || [x , y , z , w]

    float numero_2 = v4_0.r; // es equivalente a v4_0.x
    vec2 v2_2 = v4_0.rg;     // es equivalente a v4_0.xy
    vec3 v3_3 = v4_0.gbr;    // es equivalente a v4_0.yzx

    gl_FragColor = vec4(0.5,0.5,1.,1.); // [ (r, g ,b , a) ] con valores entre 0. y 1.

}
```


# Intro a GLSL

## Objetivo

* Familiarizarse con la escritura .
* Entender conceptualmente que un **fragment shader** ejecuta las mismas instrucciones en paralelo para **cada pixel** que tienen una **posicion** y renderiza un **color.**
* Entender por qué los  sistemas de referencia son importa

## Slides

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vRow4ohCvBzvlr1J_qQMQaoEP_R55iZ--e_eY8GKPg0w-FbwRsE4EsDcrWNm5ivKLyKDt-x2fG4HucI/pub?start=false&loop=false&delayms=3000>" %}

**NOTAS**

**FRAGMENT SHADER:** entra posición sale color.

* Declaración de **variables uniformes:** variables que contienen información "externa" que le programadore le puede pasr. Ejemplo: tiempo.
* void () **main** {..}: cuerpo principal de ejecución.
* **gl\_**{...}: son variables provistas para interacturar (leer y escribir información) en distintos momentos de la pipeline gráfica. Ejemplos:

  **gl\_FragCoord:** permite leer las coordenadas del píxel.

**gl\_FragColor:** permite escribir el color que se va a renderear.

## Introducimos ejes de coordenadas y funciones básicas

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vQ99JopXV48k_2kdREOpFVWIZHCN-oL808900AbbauCOPPKUPca3B-fYnZiOkcFTdIWxDBep3jDnkCc/pub?start=false&loop=false&delayms=3000>" %}

## Script: Sistemas de referencia

```glsl

float verEjes(vec2 pos){
    float ejes; 
    ejes += 1.-step(0.009, distance(pos.x,0.));
    ejes += 1.-step(0.009, distance(pos.y,0.));
    return ejes;
}

void main() {
    vec2 pos; vec3 color;
    pos = uv();
  	color.g = verEjes(pos);
    //Visualizamos los ejes
    color.rb = pos;  //[( r,b )] == [( x,y )]
        
    // Mapeamos valores para entender el rango
    //[( r,b )] == [( 1,0 )] full rojo 
    //[( r,b )] == [( 0,1 )] full azul
    //[( r,b )] == [( 1.,1. )] full rojo y azul
    //[( r,b )] == [( 0.,0. )]  sin rojo, sin azul 
    //Identificamos el rango de la variable x y de la variable y
    
    ////////////////////////////////////////////
    //Cuento la historia de Descartes y **amamos los sistemas de referencia**
    
    //Posicionamos el centro de la pantalla en el medio
    //color.rb = uvN();  //[( r,b )] == [( x,y )]
    
    gl_FragColor = vec4(color,1.); 

}
```

## Script: tiempo + funciones trigonométricas

```glsl
float verEjes(vec2 pos){
    float ejes; 
    ejes += 1.-step(0.009, distance(pos.x,0.));
    ejes += 1.-step(0.009, distance(pos.y,0.));
    return ejes;
}

void main() {
  vec2 pos = uv(); vec3 color;
  
//Parte 1. El tiempo al asignar color
  
// float freq =10.;
//color.r = cos(pos.x*freq+time);
  
// freq =20.;
//color.b = cos(pos.x*freq+time);
//color.g = cos(length(pos)*2.);
  
  
//Parte 2. El tiempo al asignar poscion
//pos.x +=cos(time);
//pos.y += sin(time);

//color += verEjes(pos);
// color.r += 1.-length(pos);
 
 

  gl_FragColor = vec4(color, 1.); // [ (r, g ,b , a) ]
  
    
}
```

## Script: figuras simples

```glsl
void main() {
  vec2 pos = uv(); vec3 color;
  float scale=1.;

  // Introducimos a las SDF : Funciones de distancias de signo
  //--------------------------------
  // Describimos figuras a partir de las posiciones de los pixeles
  float rombo    = smoothstep(0.3,0.31,distance(pos.x,0.)+distance(pos.y*0.5,0.))-scale*0.5;
  float cuadrado = smoothstep(0.3,0.31,max(abs(pos.x*.5),abs(pos.y*.5)))-scale*.5;
  float circulo  = smoothstep(0.3,0.31,length(pos));

  color.r = rombo;
  color.b = cuadrado;
  color.g = circulo;

  //Introducimos a las SDF : Funciones de distancias de signo
  //--------------------------------
  // https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm



  gl_FragColor = vec4(color, 1.); // [ (r, g ,b , a) ]

}
```

**NOTAS**

* Cada thread “obtiene” información de la posición  mediante  `gl_FragCoord`\
  ¿Cuál es el valor máximo que puede tomar? ¿Y el mínimo?
* ¿Cómo describimos la posición del píxel? ¿Es única?

  * Sistemas de representación del espacio:<br>

  <table><thead><tr><th width="132">Nombre</th><th width="92">Output</th><th>Rango</th><th>Origen de coordenas</th></tr></thead><tbody><tr><td>uvN</td><td>(x,y)</td><td>[0,1]x[0,1]</td><td>esquina inferior izquierda</td></tr><tr><td>uv</td><td>(x,y)</td><td>[-1,1]x[-1,1]</td><td>centro de la pantalla</td></tr></tbody></table>


# Introducción a mundos 3D

## Objetivo

* Enteder conceptualmente la técnica de ray marching
* Divertirse dibujando

## Slides

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vQkYbVJemT7SpYFgTh3EkR3MwreeRaeTYfW_MfmDPAj4GeWyWv2bt3zw2Lu8Pa1YqkiMZoUVu0Qjnsx/pub?delayms=3000&loop=false&start=false>" %}

## Script: raymarching simple

<figure><img src="/files/TBWRxzfTQ4sSBWgiB7GZ" alt=""><figcaption><p>Esfera simple</p></figcaption></figure>

```glsl
void main () {
    vec3 color;
    
    vec3 rd = normalize(vec3(uv(),1.5)); // Ray direction
    vec3 ro = vec3(0.,0.,-3.);         // Ray origin, podemos pensarlo donde ponemos la cámara

    float marcha; // Acumulador de las distancias calculadas
    float n;     // Acumulador para crear efecto "neon"
    
    
    for (int i=0; i<64; i++)
    {
        vec3 p =ro+marcha*rd;
        float d = length(p)-1.; // SDF para una esfera de radio 1
        
        if (d < 0.001 || marcha > 50.) {
            break;
        } 
        marcha +=d;
        n += 0.1/(.9+abs(d));
    }
 
    color +=n*0.1;
    
    gl_FragColor = vec4(color, 1.0);
}
```

### Notas

* En ray marching,  "disparamos" rayos desde la cámara (origen) hacia la escena para determinar lo que la cámara "ve".
* Cada rayo corresponde a un píxel en la pantalla, y su dirección determina hacia dónde apunta en el espacio 3D.
* La dirección del rayo:
  * necesitas proyectar el plano 2D (coordenas uv()) en el espacio 3D para determinar hacia dónde va cada rayo.
  * la **componente z** determina que tan cerca/lejos esta la proyección del espacio 2D.&#x20;
  * **normalizamos** la dirección del rayo para que las direcciones sean consistentes, es decir, midan lo mismo a la hora de empezar a marchar.

## Script: BloBs!

<figure><img src="/files/SpgXHO6ZfBXucdVICpte" alt=""><figcaption></figcaption></figure>

```glsl
float sdEsfera(vec3 p, vec3 offset, float radio){
   return length(p-offset)-radio;
}

float map(vec3 p){
    //pR(p.xz, p.y*1.+time);// Rotacion sobre el eje y
    float d1 = sdEsfera(p, vec3(cos(time)+1., sin(time*2.), 0.),1.); 
    float d2 = sdEsfera(p, vec3(cos(time)-1.,sin(time), 0.),1.); 

   float d =  smin(d1,d2,0.9);
   //d = d + + sin(p.x*10.)*0.03; // Deformaciones sobre el borde
   return d;
}

void main () {
    vec2 pos = uv(); vec3 color;
    vec3 rd = normalize(vec3(pos,1.5));
    vec3 ro = vec3(0.,0.,-10.);

    float marcha; 
    float n;
    
    for (int i=0; i<64; i++)
    {
        vec3 p =ro+marcha*rd;
        float d = map(p); 
        
        if (d < 0.001 || marcha > 50.) {
            break;
        } 
        marcha +=d;
        n += 0.1/(.9+abs(d));
    }
    
 
    color +=n*0.1;
    
    gl_FragColor = vec4(color, 1.0);
}
```

### Notas

* Vimos como hacer distorciones:
  * &#x20;rotando al rayo antes de calcular la forma.
  * luego de calcular el valor numérico de la forma, agregar una sinusoidal (**sin()**)
* Para poder describir varios objetos tomamos el mínimo valor entre las distancias de las figuras
* **smin(d1,d2,v)** es una manera suave (smooth) de unir ambas figuras. Qué tan suave sea depende del valor de **v**, a mayor **v** "más unión".

### Script: Blobs + Canvas

<figure><img src="/files/OeRypu1xZq0vtdyVPycn" alt=""><figcaption></figcaption></figure>

```glsl
float sdEsfera(vec3 p, vec3 offset, float radio){
   return length(p-offset)-radio;
}

float sdfCanvas(vec3 p){
    float td = length(p-vec3(100.))-0.01;
    
    for(int i=0; i < 10; ++i){
      for(int j=0; j<10; ++j){
          vec4 s = texture2D(channel0, vec2(float(i)/10.,float(j)/10.)); 
          float x = mix(-1.,1.,float(i)/10.);
          float y = mix(-1.,1.,float(j)/10.);
          if (s.r>0.){
              float d = sdEsfera(p,vec3(x,y,0.),0.15);
               td  = smin(d,td,0.2);
          }
         
          
      }
    }
    return td;
}


float map(vec3 p){
 //repeat(p,3.);
 //repeatLimit(p,5.,3.);

  return sdfCanvas(p);
}

void main () {
    vec2 pos = uv(); vec3 color;
    vec3 rd = normalize(vec3(pos,1.5));
    vec3 ro = vec3(0.,0.,-3.);

    float marcha; 
    float n;
    
    for (int i=0; i<64; i++)
    {
        vec3 p =ro+marcha*rd;
        float d = map(p); 
        
        if (d < 0.001 || marcha > 50.) {
            break;
        } 
        marcha +=d;
        n += 0.1/(.9+abs(d));
    }
    
 
    color +=n*0.2;
    
    gl_FragColor = vec4(color, 1.0);
}
```

### Notas

* En vez de describir la escena a través de definir SDFs matemáticamente, usamos un canvas para dibujar.
  * Leemos de la textura como si fuese una grilla 10x10, cada celda dibuja una esfera en caso de ser pintada de blanco.
  * Usamos las metaballs para dibujar blobs.&#x20;
* **Bonus:** llamando las funciones **repeat()**, y **repeatLimit()** reproducimos el espacio(sistema de coordenadas) haciendo que nuestra **sdfCanvas** se repita infinitamente, o dentro de límites definidos. \
  Esto nos permite crear patrones repetitivos o estructuras periódicas en la escena sin necesidad de definir manualmente cada instancia.&#x20;

### Extra

{% embed url="<https://www.desmos.com/calculator/7yqegqcwkb>" %}
Visualizacion de la funcion que usamos para acumular color
{% endembed %}


# Cámara y Acción

Recorriendo el espaico 3D

## Script: Transformaciones en el espacio

```glsl
float sdEsfera(vec3 p, vec3 offset, float radio){
   return length(p-offset)-radio;
}

float sdfCanvas(vec3 p){
    float td = length(p-vec3(100.))-0.01;
    
    for(int i=0; i < 10; ++i){
      for(int j=0; j<10; ++j){
          vec4 s = texture2D(channel0, vec2(float(i)/10.,float(j)/10.)); 
          float x = mix(-1.,1.,float(i)/10.);
          float y = mix(-1.,1.,float(j)/10.);
          if (s.r>0.){
              float d = sdEsfera(p,vec3(x,y,0.),0.15);
               td  = smin(d,td,0.2);
          }
         
          
      }
    }
    return td;
}


float map(vec3 p){
// Traslaciones 
//  p.x += cos(time); //En el eje x
//  p.y += sin(time); //En el eje y
//  p.z += cos(time); //En el eje z

// Rotaiones
//  pR(p.xy,time*0.1); // Rotacion con respecto al eje z
//  pR(p.zy,time*0.2); // Rotacion con respecto al eje x
//  pR(p.xz,time*0.5); // Rotacion con respecto al eje y
    
 //repeat(p,5.);
 //repeatLimit(p,5.,3.);
  return sdfCanvas(p);
}

void main () {
    vec2 pos = uv(); vec3 color;
    //Escalar 
    float fl = mouse.x/resolution.x;
    vec3 rd = normalize(vec3(pos, mix(0.5,2., fl))); 
    vec3 ro = vec3(0.,0.,-3.);
    
    

    float marcha; 
    float n;
    
    for (int i=0; i<64; i++)
    {
        vec3 p =ro+marcha*rd;
        float d = map(p); 
        
        if (d < 0.001 || marcha > 50.) {
            break;
        } 
        marcha +=d;
        n += 0.1/(.9+abs(d));
    }
    
 
    color +=n*0.2;
    
    gl_FragColor = vec4(color, 1.0);
}
```

### Notas

* **Zoom in/ Zoom Ou**t: cambiando el F.O.V (valor z de la dirección del rayo)

```glsl
float fl = 1.; // Probar: mouse.x/resolution.x
//Mayor valor, zoom in (los rayos mas paralelos)
//Menor valor. zoom out (los rayos estan mas "abiertos")
vec3 rd = normalize(vec3(pos, mix(0.5,2.,fl)); 
```

* **Rotaciones y traslaciones**: aplicamos operaciones antes de llamar la función que calcula nuestra escena
* Roaciones discretas usando la función **mix()**

```
 float a1,a2; // angulos de rotacion

  a1 = mix(PI, 0.,bpm(10.,1.,1.));
  a1 = mix(-PI,a1, bpm(20.,1.,1.)); 
    
  a2 = mix(PI, 0.,bpm(15.,1.,1.));
  a2 = mix(-PI,a2, bpm(10.,1.,1.)); 
    
  pR(p.xz,a1);
  pR(p.yz,a2); 
```


# Repaso + usando mouse y audio input

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vRPENsKd9tb8Ds58ZxGAFedWtV7jjvwtKerjUYMLEwUEaQC-NZMyMDAcXwUZQYc20purImbFLzFRn5K/pub?start=false&loop=false&delayms=3000>" %}

## Script: Blobs

```glsl
float sdEsfera(vec3 p, vec3 offset, float radio){
   return length(p-offset)-radio;
}

float sdfCanvas(vec3 p){
    float td = length(p-vec3(100.))-0.01;
    
    for(int i=0; i < 10; ++i){
      for(int j=0; j<10; ++j){
          vec4 s = texture2D(channel0, vec2(float(i)/10.,float(j)/10.)); 
          float x = mix(-1.,1.,float(i)/10.);
          float y = mix(-1.,1.,float(j)/10.);
          if (s.r>0.){
              float d = sdEsfera(p,vec3(x,y,0.),0.15);
               td  = smin(d,td,0.2);
          }
         
          
      }
    }
    return td;
}


float map(vec3 p){
    float s1 = sdEsfera(p, vec3(1.,0.,0.),.8);
    //return s1;            // 1. Retornamos 1 esfera
    
    float s2 = sdEsfera(p, vec3(-1.,0.,0.),.8);
    //return smin(s1,s2,1.); // 2. Retornamos 2 esferas "pegadas" 


    return sdfCanvas(p);    // 3. Hacemos el mismo proceso pero 
                            // sobre las cosas dibujadas en el canvas
}  

void main () {
    vec2 pos = uv(); vec3 color;
    vec3 rd = normalize(vec3(pos, mix(0.5,2., 1.))); 
    vec3 ro = vec3(0.,0.,-5.);
    
    

    float marcha; 
    float n;
    
    for (int i=0; i<64; i++)
    {
        vec3 p =ro+marcha*rd;
        float d = map(p); 
        
        if (d < 0.001 || marcha > 50.) {
            break;
        } 
        marcha +=d;
        n += 0.1/(1.4+abs(d));
    }
    
 
    color +=n*0.2;
    
    gl_FragColor = vec4(color, 1.0);
}
```

#### NOTAS

* Las transformaciones *(rotaciones)* dependen si se aplican en la función **map o** en las funciones **sdEsfera, sdfCanvas.**
* Vimos ejemplo usando la función **mix()** para controlar las rotaciones

  ```
   float a1,a2; // angulos de rotacion

    a1 = mix(PI, 0.,bpm(10.,1.,1.));
    a1 = mix(-PI,a1, bpm(20.,1.,1.)); 
      
    a2 = mix(PI, 0.,bpm(15.,1.,1.));
    a2 = mix(-PI,a2, bpm(10.,1.,1.)); 
      
    pR(p.xz,a1);
    pR(p.yz,a2); 
  ```

## Inputs de The\_Force:

* **mouse.x/resolution.x** :  es un valor de 0 a 1 que controlamos con la coordenada x del mosue
* **mouse.y/resolution.y :**&#x65;s un valor de 0 a 1 que controlamos con la coordenada y del mosue
* Para la audioreactividad habilitar el micrófono y usar:\
  **bands.x, bands.y, bands.z, bands.w**\
  que respresentan las frequencias  **bajas, medias-bajas, medias-altas y altas**, respectivamente, obtenidas tras aplicar la **Transformada Rápida de Fourier (FFT)** al sonido de entrada.


# Luz

Agregamos el modelo de phong para poder colorear

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vQETQ_yU_6-I5AMkmAFFo4IgokWBz69tZRcU4IxSn6DmsGTxmouvRSQu81v7Ke4XyDQmQ6mBGXqNPVM/pub?start=false&loop=false&delayms=3000>" %}

<figure><img src="/files/GDiwudN88TGVi3HPmnEI" alt=""><figcaption></figcaption></figure>

## Script: Modelo de Phong

```glsl
float sdEsfera(vec3 p, vec3 offset, float radio){
   return length(p-offset)-radio;
}

float sdfCanvas(vec3 p){
    float td = length(p-vec3(100.))-0.01;
    
    for(int i=0; i < 10; ++i){
      for(int j=0; j<10; ++j){
          vec4 s = texture2D(channel0, vec2(float(i)/10.,float(j)/10.)); 
          float x = mix(-1.,1.,float(i)/10.);
          float y = mix(-1.,1.,float(j)/10.);
          if (s.r>0.){
              float d = sdEsfera(p,vec3(x,y,0.),0.15);
               td  = smin(d,td,0.2);
          }
      }
    }
    return td;
}

float map(vec3 p){
  return sdfCanvas(p);
}


vec3 normal(vec3 p) {
  const float e = 0.001;
  return normalize(vec3(
    map(p + vec3(e,   0.0, 0.0))- map(p + vec3(-e,  0.0, 0.0)),
    map(p + vec3(0.0,   e, 0.0)) - map(p + vec3(0.0,  -e, 0.0)),
    map(p + vec3(0.0, 0.0,   e)) - map(p + vec3(0.0, 0.0,  -e))
  ));
}


vec3 luz(vec3 posLuz,  vec3 posActual, vec3 n, vec3 base, vec3 camDir){
    vec3 l = normalize(posLuz - posActual);
    float dif = clamp(dot(l, n),0.,1.);
    vec3 colorDif =base*dif*dif;
      
    vec3 lReflejada =normalize(reflect(-l,n));
 
    float specular = pow(clamp(dot(lReflejada, camDir),0.,1.),500.2);
    specular = min(specular,dif);
    vec3 colorSpec = teal*noise(posActual*3.)*specular;
    
    
    vec3 colorAmb = pink * 0.0001; // Si desean agregar un color ambiente

    vec3 color = colorDif + colorAmb + colorSpec;
    return color;
}

vec3 iluminacion(vec3 posActual, vec3 camaraPos){
    vec3 fuenteDeLuz = vec3(2.,.7,-3.6); //Posicion de luz 1
    vec3 color = vec3(0.8,0.7,0.); //Color de luz 1
    vec3 n = normal(posActual);
    vec3 camDir = normalize(camaraPos - posActual);
       
    vec3 colorFinal = luz(fuenteDeLuz, posActual, n, color, camDir);
    
    
    vec3 fuenteDeLuz2 = vec3(-2.,2.7,-3.6);// Posicion de luz 2
    vec3 color2 = vec3(0.8,0.,0.);   // Color de luz 2
    colorFinal += luz(fuenteDeLuz2, posActual, n, color2, camDir);;
    return colorFinal;
}

void main () {
    vec2 pos = uv(); vec3 color;
    vec3 rd = normalize(vec3(pos, 1.6));   vec3 ro = vec3(0.,0.,-3.);
    
    float marcha; vec3 p;
    float hit = 0.;
    for (int i=0; i<64; i++)
    {
        p =ro+marcha*rd;
        float d = map(p); 
        
        if (d < 0.001){ 
            hit= 1.;
            break;
        } 
        if(marcha>50.){
            break;
        }
        marcha +=d;
    }
    
    color +=iluminacion(p,ro)*hit;

    gl_FragColor = vec4(color, 1.0);
}
```


# El Canvas como controller

Si dibujamos con colores tenemos más información que nos permite ser más orgánicos en el Blobuniberse

<figure><img src="/files/OPI1aG5EMagXSWvTx4n6" alt=""><figcaption></figcaption></figure>

## Script: Demo de esferas con radios variables (color rojo), y ubicación en el eje z (color azul)

```glsl
float sdEsfera(vec3 p, vec3 offset, float radio){
   return length(p-offset)-radio;
}

float sdfCanvas(vec3 p){
    float td = length(p-vec3(100.))-0.01;
    
    for(int i=0; i < 10; ++i){
      for(int j=0; j<10; ++j){
          vec4 s = texture2D(channel0, vec2(float(i)/10.,float(j)/10.)); 
          float x = mix(-1.,1.,float(i)/10.);
          float y = mix(-1.,1.,float(j)/10.);
          if (s.r>0. || s.g >0.){
              float z = mix(.5,-.5,s.b);
              float d = sdEsfera(p,vec3(x,y,z),0.15*s.r);
               td  = smin(d,td,0.4);
          }
         
          
      }
    }
    return td;
}


float map(vec3 p){

  return sdfCanvas(p);
}


vec3 normal(vec3 p) {
  const float e = 0.001;
  return normalize(vec3(
    map(p + vec3(e,   0.0, 0.0))- map(p + vec3(-e,  0.0, 0.0)),
    map(p + vec3(0.0,   e, 0.0)) - map(p + vec3(0.0,  -e, 0.0)),
    map(p + vec3(0.0, 0.0,   e)) - map(p + vec3(0.0, 0.0,  -e))
  ));
}


vec3 luz(vec3 posLuz,  vec3 posActual, vec3 n, vec3 base, vec3 camDir){
    vec3 l = normalize(posLuz - posActual);
    float dif = clamp(dot(l, n),0.,1.);
    vec3 colorDif =base*dif*dif;
      
    vec3 lReflejada =normalize(reflect(-l,n));
 
    float specular = pow(clamp(dot(lReflejada, camDir),0.,1.),500.2);
    specular = min(specular,dif);
    vec3 colorSpec = teal*noise(posActual*3.)*specular;
    
    
    vec3 colorAmb = pink * 0.0001; // Si desean agregar un color ambiente

    vec3 color = colorDif + colorAmb + colorSpec;
    return color;
}

vec3 iluminacion(vec3 posActual, vec3 camaraPos){
    vec3 fuenteDeLuz = vec3(2.,.7,-3.6); //Posicion de luz 1
    vec3 color = vec3(0.8,0.7,0.); //Color de luz 1
    vec3 n = normal(posActual);
    vec3 camDir = normalize(camaraPos - posActual);
       
    vec3 colorFinal = luz(fuenteDeLuz, posActual, n, color, camDir);
    
    
    vec3 fuenteDeLuz2 = vec3(-2.,2.7,-3.6);// Posicion de luz 2
    vec3 color2 = vec3(0.8,0.,0.);   // Color de luz 2
    colorFinal += luz(fuenteDeLuz2, posActual, n, color2, camDir);;
    return colorFinal;
}



void main () {
    vec2 pos = uv(); vec3 color;
    vec3 rd = normalize(vec3(pos, 1.6)); 
    vec3 ro = vec3(0.,0.,-3.);
    
    

    float marcha; 
    float n;
    vec3 p;
    float hit = 0.;
    for (int i=0; i<64; i++)
    {
        p =ro+marcha*rd;
        float d = map(p); 
        
        if (d < 0.001){ 
            hit= 1.;
            break;
        } 
        if(marcha>50.){
            break;
        }
        marcha +=d;
        n += 0.1/(.9+abs(d));
    }
    
    color +=iluminacion(p,ro)*hit;

    
    gl_FragColor = vec4(color, 1.0);
}
```

### Bonus: usar el color verde para algun atributo que les gustaria que cambie!


# Lista de funciones

## Funciones de GLSL

Lista completa de funciones:

* <https://www.shaderific.com/glsl-functions>
* <https://thebookofshaders.com/glossary/>

FUNCIONES Trigonometría

* cos(x)
* -sin(x)
* tan(x)

Potencia

* pow(x, 0.5) == sqrt(x)
* pow(x, 1.)
* pow(x, 2.)
* pow(x, n) para cualquier n:=número
* sqrt(x): raiz cuadrada
* inversesqrt(x) 1./sqrt(x) \\

Exponenciales

* exp(x) : base 10
* exp2(x): base 2

Logaritmos

* log(x) : base 10
* log2(x) : base 2

Geometría

* length(x): longitud de un vector en la norma euclideana.
* distance(x,y): distancia entre x e y
* dot(x,y): producto interno entre x e y (producto escalar)\\

Otras

* abs(x) : valor absoluto de x. Ej. abs(1)=1, abs(-1)=1
* sign(x) : signo de x. Ej sign(1)=1 sign(-1)=0
* floor(x) : el numero entero más cercano que es menor a x. Ejempl: floor(3.14) = 3
* ceiling(x):el numero entero más cercano que es mayor a x. Ejemplo: ceiling(3.14) = 4
* fract(x): la parte fraccional de x. Ejmplo: fract(3.14)= .14;
* min(a,b): minimo valor entre a y b
* max(a,b): minimo valor entre a y b
* clamp(x, a, b): si \`x\` es menor a \`a\` devuelve a, si \`x\` es mayor a \`b\` devuelve \`b\`, sino devuelve \`x\`.
* mod(x, y): devuelve el resto de la division de "x dividido y"
* mix(x, y, a): x\*(1.-a)+y\*a
* step(x, a): devuelve 0 si x <= a, y devuelve 1 si x > a.
* smoothstep(x,a,b): devuelve 0 si x\<a, interpola linalmente entre 0 y 1 si a\<x<=b, devuelve 1 si x > b\\

Ejemplo para usar en explorador de funciones:

`float y = cos(pow(cos(x*x+u_time*.1),1.5)*10.-u_time);`


# Más referencias

* [screamer](https://charlieroberts.github.io/screamer/playground/): entorno de live coding específico para ray marching


# Cositas

Información random, chisme, o shitposting para que las clases no sean densas

<figure><img src="/files/z2vnaViM4OrIh2kVAA3W" alt=""><figcaption></figcaption></figure>


# Demoscenes

{% embed url="<https://www.youtube.com/watch?v=kzyF80KJhuM&list=PL9HVvEQXdWVaGzUP3ieExFQ6X-KzU2p7z&index=35>" %}

{% embed url="<https://www.youtube.com/watch?v=iw17c70uJes>" %}

{% embed url="<https://www.youtube.com/watch?v=gX7ESVZ7T6Y&list=PL9HVvEQXdWVaGzUP3ieExFQ6X-KzU2p7z>" %}

{% embed url="<https://www.demoscene.info/>" %}

## History: crack intros

{% embed url="<https://www.howtogeek.com/if-youve-never-heard-of-the-demoscene-youre-missing-out/>" %}

{% embed url="<https://freax.intro.hu/sample.html>" %}


# Blobs

## La historia de "Blobs"

* **Los Metaballs** (o “blobs”) fueron desarrollados por **Jim Blinn en los años 80** para modelado de formas orgánicas y cuerpos blandos.
* El término **"blobs"** proviene de los primeros gráficos donde las formas suaves y fusionadas parecían gotas de líquido.

#### Referencias completas&#x20;

{% embed url="<https://steve.hollasch.net/cgindex/misc/metaballs.html>" %}

#### Jim Blinn&#x20;

<figure><img src="/files/JTYhIhVSwOimygADjJtp" alt=""><figcaption><p>En la serie COSMOS de Carl Sagan</p></figcaption></figure>

<figure><img src="/files/MpzJPztxTojcTmX5zyXu" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/PCHM8MT4IO75OYMn6sxl" alt=""><figcaption></figcaption></figure>

#### Yoichiro Kawaguchi

<figure><img src="/files/I2R6MHHMrL6lM6mGPRNL" alt=""><figcaption><p>Yoichiro Kawaguchi, Eggy, 1990. Still from CGM’s interview with the artist during his 2018 exhibition “L’univers des formes” at the Centre des Arts d’Enghien-les-Bains. © Gorkab. <a href="https://medium.com/danae/new-media-precursor-yoichiro-kawaguchi-351e57dbacc2">Source</a></p></figcaption></figure>

{% embed url="<https://www.youtube.com/watch?v=HDZ6mNYX_-4>" %}


# más cositas

## Lentes de cámara

<figure><img src="/files/DViFROklODULRHvcT5zu" alt=""><figcaption><p>proyecciones en una cabza de humano</p></figcaption></figure>

## Superficies&#x20;

<figure><img src="/files/fhhozCbu8YSznEzjcFhC" alt=""><figcaption><p>curvatura negativa de una papita</p></figcaption></figure>

<figure><img src="/files/yezO45ZAIxpHWQUhbvBI" alt=""><figcaption><p><a href="https://www.instagram.com/hamidnaderiyeganeh/?hl=en">Más de su trabajo</a></p></figcaption></figure>


# TALLER: INTRODUCCIÓN AL VIDEOARTE CON CÓDIGO

Centro Cultural Recoleta en el marco del festival SPAM Arts

## Slides

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vSil5wYNfmUNs36k4nnn9y1LiuhhuLMJxabxKUoZwpTzlGyTnEWefXrfrfMbyAwxVARUQPzdk_5mdO6/pub?delayms=3000&loop=false&start=false>" %}

## Herramienta desarollada para el taller:

{% embed url="<https://spamarts-demo.solsarratea.world/>" %}

### Código fuente:

{% embed url="<https://github.com/solsarratea/spamarts-demo>" %}


# LIVECODING & CHILL

{% embed url="<https://www.youtube.com/watch?v=KpCPjK3ts5A>" %}
Programa completo
{% endembed %}

{% embed url="<https://gist.github.com/solsarratea/4241067df034bfca1302ade87aa7270b>" %}
Código Final
{% endembed %}


# SHADER JAM

Encuentro en RAD (Rejunte de Artistas Digitales) Buenos Aires, Argentina.

<figure><img src="/files/6pXZS4keg2CTucrYOjXn" alt=""><figcaption><p>"SHADER JAAAAAAAAAAM, QUIEN NECESITA FRENOS?"</p></figcaption></figure>

{% embed url="<https://pad.riseup.net/p/shader-jam>" %}


# Cables.gl

## Demo de Síntesis Granular

### Lectura de spritesheet con shader

{% embed url="<https://cables.gl/p/04PUcx>" %}

### Script de supercollider:

```supercollider
s.boot;

(
s.meter;
s.plotTree;
s.scope;
)

b = Buffer.readChannel(s, $PATH_TO_AIFF_FILE, channels: [0]);

b.plot

b.play:

FreqScope.new;

({
	var sig;

	sig = GrainBuf.ar(
		2,
		Dust.ar(100),
		0.2,
		b,
		MouseX.kr (0.5,3.1),
		(
			Phasor.ar(0, MouseY.kr (0.1,10,-1) * BufRateScale.ir (b), 0, BufSamples.ir (b)-1)
			+ LFNoise1.ar(10).bipolar (0.0* SampleRate.ir) ) / BufSamples.ir(b),
		2,
		0,
		-1,
		512
	);

	sig = sig* 0.1;

}.play)

{LFSaw.ar (10,1)}.plot(0.2)

```

## Demo de Pixel Sorting

{% embed url="<https://cables.gl/p/WT9xnz>" %}

## Demo de Steganography

{% embed url="<https://cables.gl/p/awgtdz>" %}


# Vedajs

{% embed url="<https://veda.gl/vedajs/>" %}


# Shjam

Usaremos un editor de texto web colaborativo basado en [vedajs](https://veda.gl/vedajs/).

{% embed url="<https://shjam.solsarratea.world/>" %}
Link al editor
{% endembed %}

<figure><img src="/files/5xZHf1yHwEVsCfdGCeWM" alt=""><figcaption><p>Como se ve el editor web</p></figcaption></figure>

**Keyboard controls:**

`CTRL + 0` : muestra/esconde el editor

`CTRL + ENTER`: Ejecutra el código disponible en el editor

`CTRL + 9`: habilita dibujar en simultáneo&#x20;

`SPACE`: limpia el canvas de dibujo

**Motivos de la elección:**

* vedajs funciona en [pulsar](https://pulsar-edit.dev/) (editor de texto) que tambien soporta [tidal](https://tidalcycles.org/) y es muy facil de extender y usar mouse,camara, buffers, osc, mic,etc
* &#x20;la sintaxis es igual que los shaders de <https://glslsandbox.com/> (galeria con muchisimos ejemplos)


# Demo Doodle grupal

```
// Author: Sol Sarratea @solquemal
// Title: Shader jam

precision mediump float;

uniform float time;
uniform vec2 resolution;
uniform sampler2D doodle;
uniform sampler2D backbuffer;

vec2 uv(){
    /* Devuelve las posiciones del canvas en rango [-1.,1.]x[-1.,1.] */
    vec2 pos = gl_FragCoord.xy/resolution *2.- 1. ; 
  	pos.x *= resolution.x/resolution.y;
  	return pos;
}

vec2 uvN(){
    /* Devuelve las posiciones del canvas en rango [0.,1.]x[0.,1.] */
    vec2 pos = gl_FragCoord.xy/resolution; 
    return pos;
}

void main() {
    vec2 pos; vec4 color;
    pos = uv();
 		
  	color = texture2D(doodle,uvN());
  
  	color= mix(vec4(0.,0.,0.,1.), color, step(0.9,color.a));
  
  	vec4 backbuffer = texture2D(backbuffer, uvN()*vec2(0.99+sin(pos.y*20.+time)*0.1,1.1+cos(pos.x*10.+time)*0.01));
    
        gl_FragColor = max(backbuffer*0.99,color); 

}
```


# Kodelife

{% embed url="<https://hexler.net/kodelife>" %}

## Helpers

```
uniform sampler2D midi1;
ivec2 midiCoord(int offset)
{
    int x = offset % 32;
    int y = offset / 32;
    return ivec2(x,y);
}

float setMidi(int ccNumber){
  vec4 val = texture(midi1, vec2((1./32.) * midiCoord(3 * 127 + ccNumber)));
  return val.r;
}

#define PI 3.1415926538
float bpm(float bpm, float q, float intensity){
    // Adaptacion de funcion creada por Char Stiles
    // La idea es generar una funcion que sirva como especie de metronomo.
    // Devuelve un valor entre 0 y 1
    float bps = 60./bpm; // beats por segundo
    float bpmVis = tan((time*PI/q)/bps);
     return max(min(abs(bpmVis),1.),0.) * intensity; 
}
float bpmd(float b){
    // Discrete bpm
 return step(0.5,bpm(b,1.,1.)); 
}
float luma(vec3 color) { return dot(color, vec3(0.299, 0.587, 0.114)); }

float rand(vec2 n) {
    return fract(sin(dot(n, vec2(12.9898,12.1414))) * 83758.5453);
}
```


# Live coding por TOPLAP BCN

Taller de introducción a la generación de imágenes visuales utilizando directamente la GPU (target gráfica), a partir de la escritura de un shader (programa) en GLSL, el lenguaje de shading de OpenGL

\
**Objetivos:**

* Adquirir nociones básicas de GLSL.  &#x20;
* Entender las ventajas e inconvenientes de escribir programas que funcionan directamente con la GPU.
* &#x20;Acercar el código creativo como práctica mundana.
* Crear, mostrar y participar.<br>

**Agenda:**\
Bloque 0\
11.00-11.30: Presentación y motivaciones\
11.30-11.45: Pausa/Preguntas <br>

Bloque 1\
11.45-12.30: Bloque 1: Introducción a GLSL y nociones básicas\
12.30-12.45: Exprimentacion&#x20;

12.45-13.00: Pausa \
\
Bloque 2\
13.00-13.15:  Composicion + tematica final \
13.15-13.45: Tiempo re-creativo \
13.45-14.00: Preguntas, y respuestas&#x20;

<br>


# Organización

**Workshop facilitado gracias a** [**TOPLAP BCN**](https://toplap.cat/en/home)   &#x20;

```
 / ᐢ⑅ᐢ \   ♡   ₊˚  
꒰ ˶• ༝ •˶꒱       ♡‧₊˚    ♡
./づ~ :¨·.·¨:     ₊˚  g r a c i a s
      `·..·‘    ₊˚   ♡

```

<br>


# Código de conducta

Es muy importante crear un espacio seguro entre todes 🌈

{% embed url="<https://gist.github.com/solsarratea/1409b0afe055a29e6aaa1e8e9c55d9d8>" %}


# Herramientas

Usaremos un editor de texto web colaborativo basado en [vedajs](https://veda.gl/vedajs/).

{% embed url="<https://shjam.solsarratea.world/>" %}
Link al editor
{% endembed %}

<figure><img src="/files/5xZHf1yHwEVsCfdGCeWM" alt=""><figcaption><p>Como se ve el editor web</p></figcaption></figure>

**Keyboard controls:**

`CTRL + 0` : muestra/esconde el editor

`CTRL + ENTER`: Ejecutra el código disponible en el editor

`CTRL + 9`: habilita dibujar en simultáneo&#x20;

`SPACE`: limpia el canvas de dibujo

**Motivos de la elección:**

* vedajs funciona en [pulsar](https://pulsar-edit.dev/) (editor de texto) que tambien soporta [tidal](https://tidalcycles.org/) y es muy facil de extender y usar mouse,camara, buffers, osc, mic,etc
* &#x20;la sintaxis es igual que los shaders de <https://glslsandbox.com/> (galeria con muchisimos ejemplos)


# Bloque 0

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vTvo_jr_vsS2DueyCYkgPOQMqW0bQr1UKr4nzipuQVv29HWk_aq9vIqrgi49W_V-lCeadBLGPTTOuVk/pub?start=false&loop=false&delayms=3000>" %}

**NOTAS**

* GPU permite hace muchas operaciones en simultáneo. Esto implica que scribir programas que corran en la GPU permite que tengan mejor performance, y mayor complejidad.

{% embed url="<https://glitch.com/~shader-performance>" %}
App para testear el rendimiento de CPU vs GPU en frames
{% endembed %}

{% embed url="<https://youtu.be/-P28LKWTzrI>" %}
GPU vs CPU
{% endembed %}


# Bloque 1

## Nociones básicas de GLSL

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vRow4ohCvBzvlr1J_qQMQaoEP_R55iZ--e_eY8GKPg0w-FbwRsE4EsDcrWNm5ivKLyKDt-x2fG4HucI/pub?start=false&loop=false&delayms=3000>" %}

**NOTAS**

**FRAGMENT SHADER:** entra posición sale color.

* Declaración de **variables uniformes:** variables que contienen información "externa" que le programadore le puede pasr. Ejemplo: tiempo.
* void () **main** {..}: cuerpo principal de ejecución.
* **gl\_**{...}: son variables provistas para interacturar (leer y escribir información) en distintos momentos de la pipeline gráfica. Ejemplos:

  **gl\_FragCoord:** permite leer las coordenadas del píxel.

**gl\_FragColor:** permite escribir el color que se va a renderear.

## Introducimos ejes de coordenadas y funciones básicas

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vSgf1bWJN63BgLBv_EgWdxfd3nAbnXngsjXG7aw27cvmhXCoeGtggZUic5HU22A1VemQVOotYdYn_CE/pub?start=false&loop=false&delayms=3000>" %}

**NOTAS**

* Cada thread “obtiene” información de la posición  mediante  `gl_FragCoord`\
  ¿Cuál es el valor máximo que puede tomar? ¿Y el mínimo?
* ¿Cómo describimos la posición del píxel? ¿Es única?

  * Sistemas de representación del espacio:<br>

  <table><thead><tr><th width="100">Nombre</th><th width="92">Output</th><th>Rango</th><th>Origen de coordenas</th></tr></thead><tbody><tr><td>uvN</td><td>(x,y)</td><td>[0,1]x[0,1]</td><td>esquina inferior izquierda</td></tr><tr><td>uv</td><td>(x,y)</td><td>[-1,1]x[-1,1]</td><td>centro de la pantalla</td></tr></tbody></table>
* Introducimos las funciones:

  &#x20;**cos(), step(), smoothstep(), length(), y mix()**
* Transformaciones del espacio:

  &#x20;**traslación, rotación, escalar(zoom in-zoom out)**

**HELPERS (CHECKPOINT 1)**

```
vec2 uv(){
    /* Devuelve las posiciones del canvas en rango [-1.,1.]x[-1.,1.] */
    vec2 pos = gl_FragCoord.xy/resolution *2.- 1. ; 
  	pos.x *= resolution.x/resolution.y;
  	return pos;
}

vec2 uvN(){
    /* Devuelve las posiciones del canvas en rango [0.,1.]x[0.,1.] */
    vec2 pos = gl_FragCoord.xy/resolution; 
    return pos;
}

float verEjes(vec2 pos){
    float ejes; 
    ejes += 1.-step(0.009, distance(pos.x,0.));
    ejes += 1.-step(0.009, distance(pos.y,0.));
    return ejes;
}
```

**HELPERS (checkpoint 2)**

```
vec3 tablero(vec2 pos){
  return smoothstep(vec3(0.),vec3(0.001),sin(pos.xxx*20.)*sin(pos.yyy*20.));	
}

vec2 rotacion (vec2 pos, float cantidad){
  return  pos * mat2(cos(cantidad),sin(cantidad),-sin(cantidad),cos(cantidad));
}
```


# Bloque 2

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vTmgEa31uJFfZJyNxdzPQNhaQHLyS-VzxJyWku74nEoSoo2Uwpfkv6g5Lj8RL8CsaCJKXlkOjzc305n/pub?start=false&loop=false&delayms=3000>" %}

**NOTAS**

* Agregamos otro sistema de representación del espacio:

<table><thead><tr><th width="112">Nombre</th><th width="92">Output</th><th>Rango</th><th>Origen de coordenas</th></tr></thead><tbody><tr><td>uvN</td><td>(x,y)</td><td>[0,1]x[0,1]</td><td>esquina inferior izquierda</td></tr><tr><td>uv</td><td>(x,y)</td><td>[-1,1]x[-1,1]</td><td>centro de la pantalla</td></tr><tr><td>polares</td><td>(r,o)</td><td>[0,√2]x[-PI.,PI.]</td><td>centro de la pantalla</td></tr></tbody></table>

* Cada sistema de representación permite ¨**ver**¨ con otros lentes
* Agregamos distintas maneras de medir el espacio. Distintas reglas ¨**permiten**¨ describir distintas formas.&#x20;

***Extra:***

[Superfórmula](http://paulbourke.net/geometry/supershape/) : fórmula matemática que generaliza al Teorema de Pitágoras.\
Se usa para describir curvas y formas en la naturaleza.

<figure><img src="/files/IBbcSdRaTNk2BVu5I19S" alt=""><figcaption></figcaption></figure>


# Notas finales

{% embed url="<https://docs.google.com/presentation/d/e/2PACX-1vQcRv4DAC6IxNdSiguPHjKBXZYKRKgwGlj5lhCn9CPIU7Z_06Uk3xmAFPxam4lXReO-wNgfmJGEmiPY/pub?start=false&loop=false&delayms=3000>" %}

&#x20;∧,,,∧ \
( ̳•·• ̳) \
/ づ♡ GRACIAS


# BONUS

* [Steganography](https://cables.gl/p/awgtdz)


# Cheatsheets


# Funciones de GLSL

Lista completa de funciones:

* <https://www.shaderific.com/glsl-functions>
* <https://thebookofshaders.com/glossary/>

\
FUNCIONES\
Trigonometría

* cos(x)
* -sin(x)
* tan(x)

\
Potencia

* pow(x, 0.5) == sqrt(x)
* pow(x, 1.)
* pow(x, 2.)
* pow(x, n) para cualquier n:=número
* sqrt(x): raiz cuadrada
* inversesqrt(x) 1./sqrt(x)\
  \\

Exponenciales

* exp(x) : base 10
* exp2(x): base 2

\
Logaritmos

* log(x) : base 10
* log2(x) : base 2

\
Geometría

* length(x): longitud de un vector en la norma euclideana.
* distance(x,y): distancia entre x e y
* dot(x,y): producto interno entre x e y (producto escalar)\\

Otras

* abs(x) : valor absoluto de x. Ej. abs(1)=1, abs(-1)=1
* sign(x) : signo de x. Ej sign(1)=1 sign(-1)=0
* floor(x) : el numero entero más cercano que es menor a x. Ejempl: floor(3.14) = 3
* ceiling(x):el numero entero más cercano que es mayor a x. Ejemplo: ceiling(3.14) = 4
* fract(x): la parte fraccional de x. Ejmplo: fract(3.14)= .14;
* min(a,b): minimo valor entre a y b
* max(a,b): minimo valor entre a y b
* clamp(x, a, b): si \`x\` es menor a \`a\` devuelve a, si \`x\` es mayor a \`b\` devuelve \`b\`, sino devuelve \`x\`.
* mod(x, y): devuelve el resto de la division de "x dividido y"
* mix(x, y, a): x\*(1.-a)+y\*a
* step(x, a): devuelve 0 si x <= a, y devuelve 1 si x > a.
* smoothstep(x,a,b): devuelve 0 si x\<a, interpola linalmente entre 0 y 1 si a\<x<=b, devuelve 1 si x > b\\

Ejemplo para usar en explorador de funciones:

`float y = cos(pow(cos(x*x+u_time*.1),1.5)*10.-u_time);`<br>


# Transformaciones del espacio

Helpers para jugar con transformaciones en el espacio

```
const float PI = 3.141592;

vec2 tunnel(vec2 p, float size, float time)
{
    float a = atan(p.y, p.x);
    float r = sqrt(dot(p, p));
    return vec2(a / PI, time + (size / r));
}

float distancia_p(vec2 pos, float p){
    float dp= pow(abs(pos.x),p)+pow(abs(pos.y),p);
    return pow(dp,1./p);
}


vec2 tunnelP(vec2 pos, float size, float time,float p)
{
    float a = atan(pos.y, pos.x);
    float r = distancia_p(pos,p); 
    return vec2(a / PI, time + (size / r));
}

vec2 paredes(vec2 pos, float amp, float time){
    pos.y = amp/abs(pos.y);
    pos.x *= pos.y;
    pos = fract(pos+time);	
    return pos; 
}
```

```
float reflejo(inout vec2 pos, float angle){
    vec2 normal = vec2(cos(angle),sin(angle));
    float d = dot(pos, normal);
    pos -= normal*min(0.,d)*2.;
    return smoothstep(0.03,0.,abs(d));
}

vec2 rotacion (vec2 pos, float cantidad){
      return  pos * mat2(cos(cantidad),sin(cantidad),-sin(cantidad),cos(cantidad));
}

```

{% embed url="<https://fritzm.github.io/moebius.html>" %}


# Figuras

Helpers para usar figuras

Extraidas de:

{% embed url="<https://iquilezles.org/articles/distfunctions2d>" %}

* Círculo:

```
float sdCircle( vec2 p, float r ) { 
    /* Devuelve la distancia al circulo de radio r */
    return length(p) - r; 
}
```

* Cuadrado:

```
float sdBox( in vec2 p, in vec2 b )
{  /* Devuelve la distancia al cuadrado de lados b */

    vec2 d = abs(p)-b;
    return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
}
```

Ejemplo de uso:\
\
`color += smoothstep(0.01,0.0,sdBox(pos, vec2(.3)));`

* Triángulo equilátero:

```
(https://www.shadertoy.com/view/Xl2yDW)
float sdEquilateralTriangle( in vec2 p )
{
    const float k = sqrt(3.0);
    p.x = abs(p.x) - 1.0;
    p.y = p.y + 1.0/k;
    if( p.x+k*p.y>0.0 ) p = vec2(p.x-k*p.y,-k*p.x-p.y)/2.0;
    p.x -= clamp( p.x, -2.0, 0.0 );
    return -length(p)*sign(p.y);
}
```


# Color

```
float hue2rgb(float f1, float f2, float hue) {
  // http://www.chilliant.com/rgb2hsv.html

  if (hue < 0.0)
    hue += 1.0;
  else if (hue > 1.0)
    hue -= 1.0;
  float res;
  if ((6.0 * hue) < 1.0)
    res = f1 + (f2 - f1) * 6.0 * hue;
  else if ((2.0 * hue) < 1.0)
    res = f2;
  else if ((3.0 * hue) < 2.0)
    res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0;
  else
    res = f1;
  return res;
}

// Color Space Conversion
vec3 hsl2rgb(vec3 hsl) {
  vec3 rgb;

  if (hsl.y == 0.0) {
    rgb = vec3(hsl.z); // Luminance
  } else {
    float f2;

    if (hsl.z < 0.5)
      f2 = hsl.z * (1.0 + hsl.y);
    else
      f2 = hsl.z + hsl.y - hsl.y * hsl.z;

    float f1 = 2.0 * hsl.z - f2;

    rgb.r = hue2rgb(f1, f2, hsl.x + (1.0 / 3.0));
    rgb.g = hue2rgb(f1, f2, hsl.x);
    rgb.b = hue2rgb(f1, f2, hsl.x - (1.0 / 3.0));
  }
  return rgb;
}

vec3 hsl2rgb(float h, float s, float l) { return hsl2rgb(vec3(h, s, l)); }

// INTERNAL
vec3 RGBtoHCV(vec3 rgb) {
  // Based on work by Sam Hocevar and Emil Persson
  vec4 p = (rgb.g < rgb.b) ? vec4(rgb.bg, -1.0, 2.0 / 3.0)
                           : vec4(rgb.gb, 0.0, -1.0 / 3.0);
  vec4 q = (rgb.r < p.x) ? vec4(p.xyw, rgb.r) : vec4(rgb.r, p.yzx);
  float c = q.x - min(q.w, q.y);
  float h = abs((q.w - q.y) / (6.0 * c + 1e-10) + q.z);
  return vec3(h, c, q.x);
}

vec3 rgb2hsl(vec3 rgb) {
  vec3 hcv = RGBtoHCV(rgb);
  float l = hcv.z - hcv.y * 0.5;
  float s = hcv.y / (1.0 - abs(l * 2.0 - 1.0) + 1e-10);
  return vec3(hcv.x, s, l);
}

vec3 rgb2hsl(float r, float g, float b) { return rgb2hsl(vec3(r, g, b)); }

float luma(vec3 color) { return dot(color, vec3(0.299, 0.587, 0.114)); }

vec3 hueShift( vec3 color, float hueAdjust ){
    const vec3  kRGBToYPrime = vec3 (0.299, 0.587, 0.114);
    const vec3  kRGBToI      = vec3 (0.596, -0.275, -0.321);
    const vec3  kRGBToQ      = vec3 (0.212, -0.523, 0.311);
    const vec3  kYIQToR     = vec3 (1.0, 0.956, 0.621);
    const vec3  kYIQToG     = vec3 (1.0, -0.272, -0.647);
    const vec3  kYIQToB     = vec3 (1.0, -1.107, 1.704);
    float   YPrime  = dot (color, kRGBToYPrime);
    float   I       = dot (color, kRGBToI);
    float   Q       = dot (color, kRGBToQ);
    float   hue     = atan (Q, I);
    float   chroma  = sqrt (I * I + Q * Q);
    hue += hueAdjust;
    Q = chroma * sin (hue);
    I = chroma * cos (hue);
    vec3    yIQ   = vec3 (YPrime, I, Q);
    return vec3( dot (yIQ, kYIQToR), dot (yIQ, kYIQToG), dot (yIQ, kYIQToB) );
}

vec3 saturate(vec3 cin, float amount ){
    const vec3 W = vec3(0.2125, 0.7154, 0.0721);
    vec3 intensity = vec3(dot(cin.rgb, W));
    return mix(intensity, cin.rgb, amount);
}
```


# Otras

```
float bpm(float bpm, float q, float intensity){
    // Adaptacion de funcion creada por Char Stiles
    // La idea es generar una funcion que sirva como especie de metronomo.
    // Devuelve un valor entre 0 y 1
    // para visualizar bpm https://www.desmos.com/calculator/6lvbxrudxu
 float bps = 60./bpm; // beats por segundo
 float bpmVis = tan((time*PI/q)/bps);
 return max(min(abs(bpmVis),1.),0.) * intensity; 
}

float bpmd(float b){// Discrete bpm
 return step(0.5,bpm(b,1.,1.)); 
}

```


# Bibliografía

{% embed url="<https://thebookofshaders.com>" %}

{% embed url="<https://learnopengl.com/Introduction>" %}

{% embed url="<https://www.scratchapixel.com>" %}


# Tutoriales

{% embed url="<https://inspirnathan.com/posts/47-shadertoy-tutorial-part-1>" %}


# Blogs

{% embed url="<https://blog.demofox.org>" %}

{% embed url="<https://shaderbits.com>" %}


# Historia

{% embed url="<https://www.are.na/sol-sarratea/computer-graphics-history-dctglwv0hey>" %}
Para curioses en CG
{% endembed %}


# Comunidades

{% embed url="<https://www.shadertoy.com>" %}

{% embed url="<https://shader.zone>" %}


# Streams

{% embed url="<https://www.youtube.com/c/Acegikmo>" %}

{% embed url="<https://www.youtube.com/curiouslyminded>" %}

{% embed url="<https://www.youtube.com/c/TheArtofCodeIsCool/videos>" %}

{% embed url="<https://www.twitch.tv/flopine>" %}


# Editores

{% embed url="<http://editor.thebookofshaders.com>" %}
Editor web de GLSL
{% endembed %}

{% embed url="<https://hexler.net/kodelife>" %}
Editor local de GLSL
{% endembed %}

{% embed url="<https://shawnlawson.github.io/The_Force>" %}
Editor de GLSL web
{% endembed %}

{% embed url="<https://github.com/Gargaj/Bonzomatic>" %}
Editor local de GLSL
{% endembed %}

{% embed url="<https://glslsandbox.com>" %}
Editor de GLSL web
{% endembed %}

{% embed url="<https://www.shader.place>" %}
Editor web colaborativo
{% endembed %}

{% embed url="<https://shaderbooth.com>" %}
Editor web de GLSL
{% endembed %}

{% embed url="<https://spamarts-demo.solsarratea.world>" %}
Demo - Editor web de GLSL
{% endembed %}

{% embed url="<https://www.gsn-lib.org/>" %}
Editor web con nodos
{% endembed %}

{% embed url="<https://cables.gl/home>" %}
Editor web con nodos
{% endembed %}

{% embed url="<https://www.shadertoy.com/>" %}
Editor web
{% endembed %}

{% embed url="<https://shadered.org/>" %}
Editor web
{% endembed %}


# Frameworks

{% embed url="<https://threejs.org>" %}

{% embed url="<http://regl.party>" %}


# Entrenamiento funcional

{% embed url="<https://www.desmos.com/calculator>" %}

{% embed url="<https://clases-shaders.solsarratea.world/herramientas/ninja>" %}


# TEMPLO DE SHADERS

Para fomentar la realización de piezas en GLSL.  Podemos realizar ofrendas

Accedé aquí :

{% embed url="<https://templo-shader.glitch.me>" %}

Algunas personas referentes de la comunidad:

{% embed url="<https://intro-shaders.solsarratea.world/templo>" %}
Personas Referentes (De a poco irá migrando hacia este gitbook)
{% endembed %}


# PixelSpirit

Deck de Tarot creado por Patricio Gonzalez Vivo

{% embed url="<https://github.com/patriciogonzalezvivo/PixelSpiritDeck/blob/master/imgs/header.png?raw=true>" %}
SHADER TAROT
{% endembed %}

{% embed url="<http://pixelspiritdeck.com>" %}


