Saltar al contenido

feTurbulence, feDisplacementMap y feMorphology

El ruido de Perlin dentro de SVG, sus cuatro parámetros, cómo se usa como mapa de desplazamiento, la erosión y dilatación morfológicas, y cuatro texturas completas.

feTurbulence y sus cuatro parámetros

HTML
<feTurbulence type="fractalNoise" baseFrequency="0.02" numOctaves="4" seed="7" />

baseFrequency es la frecuencia espacial del ruido, en ciclos por unidad de usuario. Valores bajos (0,005 a 0,02) dan manchas grandes; valores altos (0,5 a 2) dan grano fino. Acepta dos valores para anisotropía: baseFrequency="0.01 0.4" produce vetas horizontales, que es lo que da aspecto de madera o de agua.

numOctaves es cuántas capas de ruido se suman, cada una al doble de frecuencia y a la mitad de amplitud. Con 1 el ruido es suave; con 5 tiene detalle a todas las escalas. Cada octava duplica el coste, así que 4 o 5 es el techo razonable y 8 es una forma segura de bloquear el hilo principal.

seed inicializa el generador. Cambiarlo da un ruido distinto con las mismas características. La especificación fija el algoritmo del generador pseudoaleatorio, así que el mismo seed produce el mismo ruido en todos los motores. Eso es una garantía real y poco común.

type acepta turbulence (el valor por omisión) y fractalNoise. La diferencia: turbulence suma los valores absolutos de cada octava, lo que produce discontinuidades en las derivadas y da un aspecto nervioso, de humo o de llama. fractalNoise suma los valores con signo, lo que da un ruido suave y equilibrado alrededor del gris medio, adecuado para nubes y para mapas de desplazamiento.

Una advertencia importante: la salida de feTurbulence tiene los cuatro canales con ruido, incluido el alfa. Si la usas directamente verás un patrón de colores translúcidos, no una escala de grises. Para convertirlo en gris hay que desaturar, y para hacerlo opaco hay que forzar el alfa:

HTML
<filter id="grano" x="0" y="0" width="100%" height="100%">  <feTurbulence type="fractalNoise" baseFrequency="0.8" numOctaves="3" seed="2" />  <feColorMatrix type="matrix" values="0 0 0 0 0.5                                       0 0 0 0 0.5                                       0 0 0 0 0.5                                       0 0 0 1 0" /></filter>

Esa matriz merece una lectura: las tres primeras filas ponen los canales de color a la constante 0,5 (todo el trabajo lo hace la quinta columna) y la cuarta deja el alfa como estaba. El resultado es un gris uniforme con la transparencia moteada del ruido, que es la forma de usar el ruido como textura de opacidad.

feDisplacementMap

Toma dos entradas: in es la imagen que se va a deformar, in2 es el mapa. Para cada píxel, lee dos canales del mapa y los usa como desplazamiento.

HTML
<feDisplacementMap in="SourceGraphic" in2="ruido" scale="20"                   xChannelSelector="R" yChannelSelector="G" />

La fórmula, con los valores del mapa normalizados a 0 a 1:

Texto
P'(x,y) = P( x + scale * (canalX - 0.5), y + scale * (canalY - 0.5) )

El menos 0,5 es lo que centra el desplazamiento: un valor de 0,5 en el mapa significa desplazamiento nulo, valores menores empujan en un sentido y mayores en el otro. Por eso fractalNoise, que se centra en 0,5, es el tipo correcto para un mapa de desplazamiento, y turbulence, que se acumula hacia arriba, produce un desplazamiento sesgado.

xChannelSelector e yChannelSelector aceptan R, G, B y A. El valor por omisión de ambos es A, lo que casi nunca es lo que quieres: si dejas los dos en alfa, el desplazamiento es igual en las dos direcciones y el resultado es un cizallado diagonal, no una deformación orgánica. Pon siempre R y G explícitamente.

Textura 1: papel rugoso

HTML
<filter id="rugoso" x="-10%" y="-10%" width="120%" height="120%"        color-interpolation-filters="sRGB">  <feTurbulence type="fractalNoise" baseFrequency="0.015" numOctaves="4"                seed="11" result="ruido" />  <feDisplacementMap in="SourceGraphic" in2="ruido" scale="9"                     xChannelSelector="R" yChannelSelector="G" /></filter>

Aplicado a un text o a un path de contorno, produce el borde tembloroso de un dibujo a mano. scale controla cuánto tiembla; baseFrequency controla el tamaño de las ondulaciones. Con frecuencia baja y escala alta sale un trazo ondulado; con frecuencia alta y escala baja, un borde vibrado.

Es la técnica detrás del aspecto «dibujado a mano» de las bibliotecas de diagramas, con la diferencia de que ellas perturban la geometría y esto perturba los píxeles. La ventaja de hacerlo con filtro: funciona sobre cualquier contenido, incluido texto y bordes redondeados. La desventaja: es un efecto de rasterizado, así que no escala.

Textura 2: grano de película

HTML
<filter id="pelicula" x="0" y="0" width="100%" height="100%"        color-interpolation-filters="sRGB">  <feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="2"                seed="4" result="grano" />  <feColorMatrix in="grano" type="saturate" values="0" result="gris" />  <feComponentTransfer in="gris" result="suave">    <feFuncA type="linear" slope="0.12" intercept="0" />  </feComponentTransfer>  <feBlend in="SourceGraphic" in2="suave" mode="overlay" /></filter>

El feComponentTransfer sobre el alfa con pendiente 0,12 es lo que baja la intensidad del grano a un nivel creíble. overlay como modo de fusión mantiene el contraste original y solo añade textura.

Este filtro tiene un uso muy concreto que ya se mencionó en el nivel 20: romper las bandas de un degradado. Superpuesto a un degradado grande, el ruido desplaza el redondeo de cada píxel y las bandas desaparecen. Con slope a 0,03 el grano es imperceptible y las bandas se van igual.

feMorphology

Dilata o erosiona una imagen: para cada píxel, toma el máximo (dilatar) o el mínimo (erosionar) de sus vecinos dentro de un radio.

HTML
<feMorphology operator="dilate" radius="2" in="SourceAlpha" result="gordo" /><feMorphology operator="erode"  radius="2" in="SourceAlpha" result="flaco" />

radius acepta uno o dos valores. Y hay que saber que la implementación usa un kernel rectangular, no circular, así que las esquinas de una forma dilatada salen cuadradas. Con radios pequeños no se nota; con radios grandes, sí, y no hay forma de evitarlo dentro de SVG.

Textura 3: contorno exterior

Restar el original de su versión dilatada da un contorno de grosor exacto, que es algo que el trazo no puede hacer sobre una silueta compuesta:

HTML
<filter id="contorno" x="-20%" y="-20%" width="140%" height="140%"        color-interpolation-filters="sRGB">  <feMorphology in="SourceAlpha" operator="dilate" radius="3" result="gordo" />  <feComposite in="gordo" in2="SourceAlpha" operator="out" result="anillo" />  <feFlood flood-color="#f9e2af" result="tinta" />  <feComposite in="tinta" in2="anillo" operator="in" result="borde" />  <feMerge>    <feMergeNode in="borde" />    <feMergeNode in="SourceGraphic" />  </feMerge></filter>

Es la manera de poner un contorno a un texto con varias palabras, a un icono con varias piezas, o a una imagen con transparencia, sin que el contorno se meta entre las piezas. Un stroke haría el contorno de cada letra por separado; esto lo hace de la silueta conjunta.

Textura 4: cristal líquido

Combinando desplazamiento con un ruido de baja frecuencia y anisotrópico:

HTML
<filter id="liquido" x="-15%" y="-15%" width="130%" height="130%"        color-interpolation-filters="sRGB">  <feTurbulence type="fractalNoise" baseFrequency="0.008 0.03"                numOctaves="2" seed="19" result="ondas" />  <feDisplacementMap in="SourceGraphic" in2="ondas" scale="28"                     xChannelSelector="R" yChannelSelector="G" result="deformado" />  <feGaussianBlur in="deformado" stdDeviation="0.6" /></filter>

La frecuencia anisotrópica (0.008 0.03) da ondas alargadas en horizontal, que es lo que sugiere agua. El desenfoque final de 0,6 suaviza los saltos que deja el desplazamiento en las zonas de gradiente fuerte.