Saltar al contenido

iridescence y anisotropy: interferencia y metal cepillado

Dos capas que atacan límites distintos del modelo de microfacetas: una añade física ondulatoria y otra rompe la simetría del lóbulo especular.

Iridiscencia: interferencia, no reflexión

Cuando una película muy fina cubre una superficie, la luz se refleja dos veces: en la cara superior de la película y en la inferior. Los dos rayos vuelven a juntarse desfasados, y ese desfase depende del grosor de la película, del ángulo de incidencia y de la longitud de onda. Algunas longitudes se refuerzan y otras se cancelan, así que el color reflejado cambia con el ángulo.

Es física ondulatoria pura, y ninguna BRDF de microfacetas la contiene, porque el modelo de microfacetas es óptica geométrica: rayos que rebotan, sin fase. Por eso iridescence no es un efecto estético añadido, es un término que el modelo base no puede producir.

Tres propiedades la controlan y las tres tienen significado físico:

  • iridescence, de cero a uno, cuánto pesa la capa.
  • iridescenceIOR, el índice de refracción de la película, 1.3 por defecto.
  • iridescenceThicknessRange, un array de dos números en nanómetros, [100, 400] por defecto.

Esos nanómetros son literales: el rango de grosores de película que producen colores en el espectro visible está entre unos cien y unos ochocientos nanómetros, del orden de la longitud de onda de la luz. Si pones valores de orden mil o superiores, los ciclos de interferencia se aprietan tanto que el resultado se vuelve gris ruidoso, que es exactamente lo que pasa con una capa gruesa en la realidad.

JS
import * as THREE from 'three';// Pompa de jabon: base transmisiva, pelicula fina, grosor variable.const pompa = new THREE.MeshPhysicalMaterial({  transmission: 1,  thickness: 0,  roughness: 0.02,  metalness: 0,  iridescence: 1,  iridescenceIOR: 1.33,  iridescenceThicknessRange: [100, 700]});// Titanio anodizado: base metalica, pelicula de oxido delgada.const anodizado = new THREE.MeshPhysicalMaterial({  color: 0x8a8f96,  metalness: 1,  roughness: 0.25,  iridescence: 0.8,  iridescenceIOR: 2.4,      // el oxido tiene indice alto  iridescenceThicknessRange: [200, 400]});

Sin iridescenceThicknessMap, el grosor es constante y vale el máximo del rango, no la media. Eso importa: cambiar solo el primer número del array no hace nada si no hay mapa. Con iridescenceThicknessMap, el grosor se interpola entre los dos extremos usando el canal verde de la textura, y ahí es donde aparece el patrón de manchas de color que hace creíble una pompa o una mancha de aceite. iridescenceMap modula la intensidad con el canal rojo.

Anisotropía: el lóbulo deja de ser redondo

La rugosidad de un MeshStandardMaterial es un solo número, lo que implica que las microfacetas están distribuidas igual en todas las direcciones y el brillo es redondo. En muchos materiales reales no lo es: el metal cepillado, el vinilo, un disco de aluminio torneado, el pelo, la seda. Todos tienen surcos orientados, y su brillo se estira perpendicularmente a esos surcos.

anisotropy introduce una segunda rugosidad. En el shader:

GLSL
material.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );material.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;material.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;

La rugosidad a lo largo de la bitangente sigue siendo la del material; la rugosidad a lo largo de la tangente crece hacia uno según la anisotropía. Con anisotropy: 1, alphaT vale uno, es decir, rugosidad máxima en una dirección y la original en la otra: el brillo se convierte en una línea.

anisotropyRotation gira esa dirección en radianes, medidos desde la tangente y en sentido antihorario. anisotropyMap permite variarla por texel, y su empaquetado es peculiar: los canales rojo y verde llevan la dirección codificada de menos uno a uno, y el canal azul lleva la intensidad de cero a uno.

JS
const acero = new THREE.MeshPhysicalMaterial({  color: 0xb8bcc2,  metalness: 1,  roughness: 0.35,  anisotropy: 0.9,  anisotropyRotation: Math.PI / 2   // surcos girados 90 grados});

Cuándo merecen la pena

iridescence es un efecto de alta visibilidad y coste moderado: dos evaluaciones de Fresnel de película fina en lugar de una de Schlick, más el muestreo del mapa de grosor si lo hay. Cuando el material lo pide, no hay sustituto; cuando no lo pide, se nota como un tinte irreal. Los casos legítimos son pocos y muy identificables: pompas, manchas de aceite o gasolina, nácar, élitros de insecto, metales anodizados, revestimientos ópticos, y ciertos plásticos holográficos.

anisotropy es más barata pero más exigente con los assets, por lo del desenvolvido. Los casos son metal cepillado o torneado, vinilo, pelo y tela de fibra alineada. Fuera de ahí, un normalMap con surcos finos produce un efecto parecido a distancia media y no depende de las tangentes.

Las dos comparten una característica con clearcoat y transmission: sus setters incrementan la versión del material al cruzar el cero, así que animarlas desde apagadas fuerza una recompilación. Y las dos requieren un entorno decente para verse, porque su efecto es sobre todo sobre la reflexión especular, no sobre el difuso.