learn GLSL from zero
ToolsCrea con shadersShader MakerCrea shaders gratis en líneaToolkitObras de shaders listas para tu webSketcher LabPinta el hero de tu landing con shaders3D StudioEl editor Three.js en tu navegador
GamesJuega con shadersOnomatoShaderEscribe una palabra y explótalaThe WatcherUn ojo que te sigueAetherVidrio líquido con un ojo adentroBloomcoreUna palabra hace crecer un jardín de luzPyrokineAvienta fuego a la paredVoltaicLa pirámide lanza rayosSurfSurfea un océano de shader

Lección 1 de 10 · Patrones en shaders

Figuras

Anillos, cuadrados, diamantes. Cada forma es una ecuación de distancia.

En Start Here cada pixel preguntaba ¿qué color soy? Una forma responde una pregunta más fina: ¿qué tan lejos estoy de esta orilla?

Antes de medir distancias, una herramienta nueva: M. Es un vec2 que siempre trae la posición del mouse, normalizada entre 0 y 1, viene del navegador y se actualiza en cada frame. En el shader la traducimos al mismo espacio que p con una sola línea:

vec2 m = (2.*M*R - R) / min(R.x, R.y);

Ahora m vive en el mismo mundo que p, el cursor es una coordenada más, lista para entrar a las ecuaciones.

Cada forma es una función de distancia. length(p) - .65 es positivo afuera del anillo, negativo adentro, y cero exactamente en la orilla. Lo mismo pasa con el cuadrado y con el diamante, solo cambia la manera de medir.

Una ecuación. Una forma. Tres reglas para medir distancia.

M y mM viene del navegador, el mouse en coordenadas normalizadas (0 a 1). m es M traducido al mismo espacio que p, donde el centro de la pantalla es (0,0). Esa fórmula (2.*M*R - R) / min(R.x, R.y) la vas a ver en cada lección con interacción.
El truco de la distanciaEl anillo mide con length(p), la regla recta desde el centro. El cuadrado mide con max, la coordenada más grande gana. El diamante mide con +, la suma de las dos coordenadas. Tres reglas, tres geometrías.
PruebaMueve el mouse adentro y afuera. Cada forma se calienta cuando el cursor cruza su orilla, la distancia es continua, no binaria. Cambia el .65 del anillo a .85 y el anillo se aleja del centro.

El código

void main(){
  vec2 p = (2.*gl_FragCoord.xy - R) / min(R.x, R.y);
  vec2 m = (2.*M*R - R) / min(R.x, R.y);

  vec3 col = vec3(0.025, 0.018, 0.035);

  float dRing    = abs(length(p) - .65);
  vec2  sq       = abs(p) - .42;
  float dSquare  = max(sq.x, sq.y);
  float dDiamond = abs(p.x) + abs(p.y) - .25;

  float hRing    = exp(-abs(length(m) - .65) * 3.);
  vec2  msq      = abs(m) - .42;
  float hSquare  = exp(-abs(max(msq.x, msq.y)) * 3.);
  float hDiamond = exp(-abs(abs(m.x) + abs(m.y) - .25) * 3.);

  vec3 cRing    = vec3(.98, .55, .12);
  vec3 cSquare  = vec3(.85, .25, .08);
  vec3 cDiamond = vec3(.96, .80, .28);

  col += cRing    * smoothstep(.018, 0., abs(dRing))
       + cRing    * exp(-abs(dRing)    * 5.) * (.30 + hRing    * .9);
  col += cSquare  * smoothstep(.018, 0., abs(dSquare))
       + cSquare  * exp(-abs(dSquare)  * 5.) * (.30 + hSquare  * .9);
  col += cDiamond * smoothstep(.018, 0., abs(dDiamond))
       + cDiamond * exp(-abs(dDiamond) * 5.) * (.30 + hDiamond * .9);

  gl_FragColor = vec4(col, 1.);
}
close