
Esfera de grano
estudio de shaders
Resumen
Un shader GLSL que genera grano animado sobre una geometría esférica, con capas de ruido que se desplazan a distinta velocidad para simular película.
La idea
El grano de película no pertenece a lo que se está filmando. Pertenece al soporte. Por eso, cuando la cámara se mueve, el grano no se mueve con la escena: se queda donde está, y la imagen pasa por detrás.
Casi todos los shaders de grano hacen justo lo contrario —ruido sobre las coordenadas de la superficie, que viaja pegado al objeto— y por eso se ven como una textura y no como película.
El grano vive en la pantalla, no en el objeto
La decisión que define todo lo demás es una línea: el ruido se evalúa sobre
gl_FragCoord, la coordenada del píxel, y no sobre las UV ni sobre la normal.
float g = hash12(gl_FragCoord.xy);
float on = step(g, uParticleDensity);Qué píxeles son partícula queda decidido de una vez y no cambia nunca. La esfera gira, respira y se desplaza por debajo de una piel que está quieta.
Esto tiene una consecuencia que no había previsto y que terminó siendo el motivo de conservarlo: la esfera y el campo de partículas del fondo comparten la misma piel. Son dos objetos distintos, con geometrías distintas, evaluando la misma función sobre la misma coordenada de pantalla. Donde se solapan, el grano coincide exactamente.
El hash es el de Dave Hoskins, sin sin(). La versión con seno es la que todo
el mundo copia y produce artefactos de rejilla en cuanto la resolución sube,
porque su periodicidad se alinea con la del píxel.
/media/projects/grain-sphere-shader/01-screen-space.webpLa onda atraviesa el cuerpo
Si todos los píxeles encendidos brillaran igual, esto sería estática. Lo que le da forma es una onda plana que viaja a través del volumen:
float w1 = 0.5 + 0.5 * sin(
dot(vWorldPos, normalize(vec3(0.8, 0.45, 0.35))) * uWaveFreq
- uTime * uWaveSpeed);El producto punto entre la posición en el mundo y una dirección fija convierte el espacio en una sola cifra: la distancia a lo largo de esa dirección. Los frentes de onda son planos que barren la esfera, así que la banda iluminada envuelve el cuerpo mientras avanza en vez de deslizarse por su superficie. Una segunda onda, mucho más débil y en otra dirección, rompe la regularidad de la primera.
/media/projects/grain-sphere-shader/02-wavefront.webpEl borde
Falta el volumen. Sin él la esfera es un disco: una silueta redonda rellena de grano, sin ninguna señal de que hay una cara mirando a la cámara.
float ndv = clamp(dot(normalize(vNormal), viewDir), 0.0, 1.0);
float volume = 0.25 + 0.75 * smoothstep(0.0, 0.9, ndv);
float W = pow(wave, 1.8) * volume;Lo que mira a la cámara se enciende; lo que se va de canto se deshace hasta un 25%, no hasta cero — un borde que llega a cero se recorta contra el fondo y vuelve a leerse como un disco, esta vez con un contorno duro.
El pow(wave, 1.8) es lo que separa la onda del fondo. Sin él, el mínimo de una
sinusoide sigue siendo luz, y el cuerpo entero queda tenuemente encendido todo
el tiempo.
Respirar
La geometría hace una sola cosa, en el vertex shader: la esfera entera se hincha y se asienta, multiplicando la posición por un factor que oscila. No es una deformación por vértice, es una sola masa cambiando de tamaño.
Es el único movimiento del que la esfera es dueña. Todo lo demás —las poses de ruta, la escala al navegar— lo escribe GSAP desde fuera, y esa separación es justamente la regla que el resto del sitio también sigue: un solo escritor por propiedad.


