Iluminación y sombreado

Del modelo de Phong a los mapas de superficie

Computación Gráfica · 2026 · Federico Marino

Índice

2 / 87
0 · Antes de empezar

Modelo de iluminación ≠ algoritmo de sombreado

MeshPhongMaterial fija el modelo; evaluarlo por fragmento es el algoritmo. Dos decisiones, una sola línea de API.

3 / 87
0 · Antes de empezar

El pipeline: dónde se calcula la luz

Renderizar es generar una imagen 2D a partir de una descripción 3D. Son cuatro problemas distintos, no uno.

4 / 87
1 · Qué hace la luz cuando toca una superficie

Luz y superficies

Un fotón que llega a una interfaz tiene exactamente tres destinos posibles.

Lo que decide el balance

La proporción entre los tres depende del material y del ángulo de incidencia. Esa dependencia angular tiene nombre —efecto Fresnel— y se ve en la slide 08.

5 / 87
1 · Qué hace la luz cuando toca una superficie

Iluminación local vs. global

Iluminación local

diffuse_bounces = 0Lo que no recibe luz directa queda negro.

Iluminación global

diffuse_bounces = 8Aparecen inter-reflexiones y sangrado de color.

Lo que Phong no calcula

Phong y Blinn-Phong no pueden calcular inter-reflexiones: las sustituyen por una constante, el término ambiente.

El costo de los rebotes

En local, cada punto se calcula sólo con las fuentes. En global depende de toda la escena: si cada rebote abriera $n$ rayos, $k$ rebotes serían $n^k$ rayos por píxel. El costo crece exponencialmente.

Sangrado de color

Una superficie iluminada rebota luz teñida de su propio color. En la imagen de la derecha, el costado izquierdo de la caja alta sale rojizo y el derecho de la caja baja, verdoso.

1 · Qué hace la luz cuando toca una superficie

Reflexión especular y difusa

No son dos fenómenos distintos: son el mismo fenómeno a dos escalas de rugosidad.

Las dos se unifican

La BRDF describe las dos con una sola función: cuánta luz que entra por una dirección sale por otra. Especular y difusa son dos formas de esa función.

7 / 87
1 · Qué hace la luz cuando toca una superficie

Refracción: la ley de Snell

Lo que no se refleja, entra. Y al entrar, cambia de dirección.

\[n_1 \sin\theta_1 = n_2 \sin\theta_2\]
  • $n$ es el índice de refracción del medio: vacío 1.00 · aire 1.0003 · agua 1.33 · vidrio 1.52 · diamante 2.42.
  • Al pasar a un medio más denso ($n_2 > n_1$) el rayo se acerca a la normal.
  • Por encima de un ángulo crítico no hay transmisión: reflexión total interna.
Un dato para la clase

Hughes registra que la ley de refracción ya era conocida por Ibn Sahl de Bagdad hacia 984 d.C., seis siglos y medio antes de Snell. El nombre es una convención, no un crédito.

Phong no modela nada de esto. La refracción no aparece en este capítulo: requiere trazar el rayo dentro del objeto, que es un algoritmo de iluminación global.

8 / 87
1 · Qué hace la luz cuando toca una superficie

El efecto Fresnel

El reparto entre reflexión y transmisión no es una constante del material: depende del ángulo.

\[F(\theta) = R_0 + (1 - R_0)(1 - \cos\theta)^5\]
  • Dieléctricos (plástico, vidrio, agua): $R_0 \approx 0.04$. Casi todo entra.
  • Conductores (metales): $R_0 \approx 0.5$ a $1.0$, y coloreado por el metal.
Phong tampoco modela esto

En Phong, $k_s$ es una constante: el brillo no cambia con el ángulo de vista. Por eso un piso de madera renderizado con Phong nunca tiene ese reflejo alargado que sí se ve en el mundo real cuando mirás casi de canto.

9 / 87
1 · Qué hace la luz cuando toca una superficie

Iluminación global: calcular los rebotes

La luz que llega a una superficie no viene solo de las fuentes: viene de todo lo demás.

Cada superficie iluminada ilumina a su vez a las demás, así que la luz que sale de un punto depende de la que sale de todos los otros. Eso es la ecuación de rendering (Kajiya, 1986). Su solución es una suma de rebotes: la luz directa, más la de un rebote, más la de dos… Cada término aporta menos que el anterior, porque en cada rebote se absorbe una parte.

  • Radiosidad: divide la escena en parches y resuelve un sistema lineal, un valor por parche. Sólo superficies difusas; el resultado sirve para cualquier punto de vista.
  • Path tracing: desde la cámara, sigue un solo camino aleatorio por muestra y promedia muchos. Es lento y tiene ruido, pero converge a la solución correcta. Es lo que usa Cycles.
  • Photon mapping: primero dispara fotones desde las luces y guarda dónde caen; después estima la luz en cada punto con los fotones cercanos.
1 · Qué hace la luz cuando toca una superficie

Medios participativos

Hasta acá supusimos que entre los objetos hay vacío. No lo hay.

\[I(d) = I_0 \, e^{-\sigma d}\]
  • Niebla, humo, polvo, agua: la luz se absorbe y se dispersa en el camino, no solo en las superficies.
  • Ley de Beer-Lambert: la intensidad decae exponencialmente con la distancia recorrida.
  • $\sigma$ es el coeficiente de extinción del medio.

Scene.fog y FogExp2 implementan exactamente esto. FogExp2 es la forma exponencial de la fórmula de arriba; Fog a secas es una interpolación lineal más barata y menos física.

11 / 87
1 · Qué hace la luz cuando toca una superficie

Dispersión subsuperficial

En algunos materiales, la luz entra, se pierde adentro, y sale por otro lado.

  • Piel, cera, mármol, leche, hojas, jade: la luz penetra la superficie.
  • Adentro rebota muchas veces contra partículas microscópicas.
  • Sale por un punto $P_o$ distinto del de entrada $P_i$, milímetros más allá.
  • Por eso una mano contra una linterna se ve roja: la luz atravesó el tejido.
Rompe el supuesto de la BSDF

Toda la maquinaria de BRDF y BTDF asume $P_i = P_o$. Acá eso es falso, y no es un detalle: hace falta una función distinta, la BSSRDF, que toma los dos puntos como argumentos. Lo vemos en la slide siguiente.

12 / 87
1 · Qué hace la luz cuando toca una superficie

BSDF: la función que describe al material

\[\text{BSDF}(\omega_i, \omega_o) = \text{BRDF}(\omega_i, \omega_o) + \text{BTDF}(\omega_i, \omega_o)\]
  • BRDF — Bidirectional Reflectance Distribution Function: la luz que sale por el hemisferio de reflexión.
  • BTDF — Transmittance: la luz que sale por el hemisferio de transmisión.
  • Responde una sola pregunta: de la luz que entra por $\omega_i$, ¿cuánta sale por $\omega_o$?
Dónde deja de alcanzar

Supone que la luz entra y sale en el mismo punto P. En piel o mármol entra en $P_i$ y sale más allá, en $P_o$: ahí hace falta la BSSRDF.

Dónde entra Phong

Phong es una BRDF concreta; Cook-Torrance es otra. La BRDF es la categoría, no un modelo.

13 / 87
2 · Las simplificaciones del tiempo real

Tres simplificaciones para llegar a 60 fps

Acá se termina la física y empieza la ingeniería. Todo lo que sigue es deliberadamente falso.

14 / 87
2 · Las simplificaciones del tiempo real

RGB: física contra percepción

La luz no viene en tres colores. Nosotros sí la vemos en tres.

  • En la naturaleza la luz es una distribución espectral continua $P(\lambda)$.
  • La retina tiene tres tipos de cono: S (~420 nm), M (~534 nm), L (~564 nm).
  • RGB no es una propiedad de la luz: es una aproximación a cómo la muestrea el ojo humano (teoría triestímulo).
El malentendido frecuente

Decir «se computan las frecuencias roja, verde y azul» sugiere que la luz tiene esas tres frecuencias. No las tiene: el espectro es continuo. Se computan tres canales porque tenemos tres tipos de cono, no porque el espectro tenga tres partes.

Qué se pierde

Con 3 canales no se puede simular dispersión cromática (el arcoíris de un prisma) ni fluorescencia. Un motor que los necesite tiene que renderizar espectralmente, con decenas de bandas.

15 / 87
3 · Fuentes de luz

Fuentes reales contra fuentes idealizadas

La misma escena, la misma potencia total. Lo único que cambia es el tamaño del emisor.

Fuente de área

emisor de 130 × 105 cmSombras con penumbra: transición gradual.

Fuente puntual

emisor de 2 × 2 cmSombras infinitamente duras.

Por qué idealizamos

Calcular la sombra de una fuente con tamaño exige integrar sobre su superficie. Un punto reduce eso a un solo vector $\mathbf{L}$. El precio es el borde de navaja de la columna derecha.

16 / 87
3 · Fuentes de luz

Luz ambiente

\[I_a = k_a \odot i_a\]
  • $k_a$ — coeficiente del material, RGB en $[0,1]^3$.
  • $i_a$ — intensidad/color de la luz ambiente.
  • $\odot$ — producto componente a componente: un filtro óptico.
Defecto crítico, y es el punto de la slide

Es constante en toda la superficie: un rincón cóncavo recibe lo mismo que una cara expuesta. Justo al revés de lo que pasa en la realidad.

AmbientLight. Los motores lo reemplazan por Ambient Occlusion, que modula esta constante según cuán ocluido está el punto.

Solo ambiente · un disco plano
Ambiente + difusa · vuelve a ser una esfera
17 / 87
3 · Fuentes de luz

Luz hemisférica

Un paso barato: que la ambiente deje de ser una constante.

\[I_{hemi} = \tfrac{1 + \mathbf{N}\cdot\mathbf{Up}}{2}\, C_{cielo} + \tfrac{1 - \mathbf{N}\cdot\mathbf{Up}}{2}\, C_{suelo}\]
  • Cuesta un producto escalar más que la ambiente y ya devuelve información de forma.

Misma esfera, misma cámara, misma intensidad total: toda la diferencia la hace un producto escalar, N·Up. En Three.js es HemisphereLight(skyColor, groundColor, intensity).

skyColor#6FB3FF
groundColor#8A5A2B
HemisphereLight
AmbientLight
18 / 87
3 · Fuentes de luz

Luz direccional

El Sol, o cualquier fuente tan lejana que ya no importa dónde está.

\[p_{luz} = (x, y, z, 0)^T\]
  • Definida por una dirección, no por una posición.
  • $\mathbf{L}$ es constante para todos los puntos de la escena: se calcula una vez.
  • No hay atenuación: $f_{att}(d) = 1$.
  • En coordenadas homogéneas se distingue por la cuarta componente: $w = 0$.

DirectionalLight. Su position no es una posición: define la dirección desde la que llega la luz hacia el target.

19 / 87
3 · Fuentes de luz

Luz puntual y atenuación

Acá aparece la distancia, y con ella el problema más viejo del modelo.

\[f_{att}(d) = \min\!\left(1,\ \frac{1}{a + bd + cd^2}\right)\]
  • Emite en todas las direcciones desde una posición fija. $w = 1$.
  • Por fragmento: $\mathbf{L} = (P_{luz} - P)/\|P_{luz} - P\|$ y $d = \|P_{luz} - P\|$.
  • La ley física $1/d^2$ es correcta e inservible: diverge cuando $d \to 0$. El resto —el denominador cuadrático, el $\min(1,\cdot)$— son parches encadenados sobre ese problema.
Hughes sobre el min(1, ·)

«there's no reasonable explanation for the “min” in the expression except that “things got dark too fast otherwise”». Vale citarlo tal cual: muestra que estas fórmulas son parches históricos, no leyes derivadas.

PointLight: decay = 2 es la ley cuadrática, decay = 0 no atenúa. distance recorta a cero — otro parche, este por performance.

20 / 87
3 · Fuentes de luz

Luz spot

Una puntual a la que se le recorta el cono. Y el recorte necesita dos ángulos, no uno.

\[I_{cono} = \mathrm{clamp}\!\left(\frac{\cos\theta - \cos\gamma}{\cos\phi - \cos\gamma},\ 0,\ 1\right)\]
  • Parámetros: posición $S$, dirección $\mathbf{D}_{spot}$, y dos ángulos.
  • $\phi$ = innerCutoff: hasta acá, intensidad plena.
  • $\gamma$ = outerCutoff: de $\phi$ a $\gamma$, la intensidad cae a cero.
  • Con un solo ángulo el borde sería un escalón: se ve el recorte.
Por qué con cosenos y no con ángulos

$\cos\theta$ ya lo tenemos: es $-\mathbf{L}\cdot\mathbf{D}_{spot}$, un producto escalar que la GPU hace gratis. El ángulo costaría un $\arccos$ por fragmento.

SpotLight expone angle (el externo) y penumbra ∈ [0,1]: qué fracción del cono es zona de caída.

21 / 87
3 · Fuentes de luz

Luz de área rectangular

La única fuente de esta lista que se parece a algo real. Y la que Phong no puede resolver.

  • La luz se emite desde una superficie con ancho y alto reales.
  • Produce penumbras auténticas, no aproximadas.
  • Requiere integrar la irradiancia sobre el área: $L_r = \int_A \ldots \, dA$.
  • En tiempo real se resuelve con LTC (Linearly Transformed Cosines) o Monte Carlo, no con Phong directo.

RectAreaLight existe en Three.js pero no proyecta sombras: el cálculo de sombra de una fuente extensa no entra en el presupuesto de tiempo real.

22 / 87
Interactiva
3 · Fuentes de luz

Probemos todas las luces

Una tetera, un piso y las seis fuentes del bloque: encendé cada una, combinalas y mové sus parámetros.

Three.js r160 · tetera: «The Utah Teapot», 3D graphics 101 (Sketchfab), CC BY-NC 4.023 / 87
4 · El modelo de Phong

El modelo de Phong

Bui Tuong Phong, tesis doctoral 1973, publicado en ACM en 1975.

\[I = I_a + I_d + I_s\]
$I_a$ambiente: la luz que llega de toda la escena, aproximada por una constante
$I_d$difusa: la luz que se reparte igual en todas las direcciones
$I_s$especular: el brillo, que depende de dónde está la cámara
  • Es un modelo empírico: no se deriva de la física, se ajusta a lo que se ve.
  • Es un modelo local: no sabe que existen otros objetos en la escena.
  • Descompone la reflectancia en tres términos independientes que se suman.
Qué NO es

No conserva energía. Puede devolver más luz de la que recibe si los coeficientes están mal elegidos. No es un defecto de implementación: el modelo no lo pretende. La conservación estricta llega con PBR.

Por qué sobrevivió cincuenta años

Porque es barato y porque se ve bien. Tres productos escalares y una potencia por fragmento. Hughes es duro con él —«this entire model, especially the "ambient term", was a terrible thing»— y aun así sigue en todos los motores.

24 / 87
Interactiva
4 · El modelo de Phong

Los vectores en el punto P

Cinco vectores. Todos unitarios. Todo el resto de la clase se escribe con estos.

  • $\mathbf{N}$ — normal a la superficie en $P$.
  • $\mathbf{L}$ — hacia la fuente (no desde ella: es el error de signo más común).
  • $\mathbf{V}$ — hacia la cámara.
  • $\mathbf{R}$ — reflejo de $\mathbf{L}$ respecto de $\mathbf{N}$.
  • $\mathbf{H}$ — bisectriz de $\mathbf{L}$ y $\mathbf{V}$. Pertenece a Blinn-Phong, se usa en la slide 30.
\[\mathbf{R} = 2(\mathbf{N}\cdot\mathbf{L})\mathbf{N} - \mathbf{L}\]
\[\mathbf{H} = \dfrac{\mathbf{L} + \mathbf{V}}{\|\mathbf{L} + \mathbf{V}\|}\]
Todos tienen que estar normalizados

Si no lo están, los productos escalares dejan de ser cosenos. Shirley lo llama «a very common error in shading computations».

25 / 87
4 · El modelo de Phong

Las tres componentes

Phong no es una fórmula: son tres fórmulas que se suman.

Ambiente
+

Nivel base constante. No aporta forma.

Difusa
+

Depende de la orientación respecto de la luz. Aporta el volumen.

Especular
=

Depende de dónde está la cámara. Aporta el brillo.

Total

La suma. Cada término resuelve algo que los otros no.

Por qué aditivo

La luz se suma: dos fuentes iluminando un punto dan la suma de sus contribuciones. Esa linealidad es lo que permite estudiar el modelo término por término.

26 / 87
Interactiva
4 · El modelo de Phong

Componente ambiente

El término más simple, y el que más confusión genera en la implementación.

\[I_a = k_a \odot i_a\]
  • $k_a \in [0,1]^3$ — reflectancia ambiental del material.
  • $i_a$ — color/intensidad de la luz ambiente.
\[I_a = (k_{a,r}\, i_{a,r},\ k_{a,g}\, i_{a,g},\ k_{a,b}\, i_{a,b})\]
No colapsa a un número

No es un producto escalar: es un filtro, y el resultado sigue siendo un color.

Aplica a los tres términos

El mismo producto se usa en $k_d \odot i_d$ y $k_s \odot i_s$: se explica una vez acá y vale para toda la ecuación.

27 / 87
Interactiva
4 · El modelo de Phong

Componente difusa

Ley de Lambert: la luz recibida depende solo del ángulo con la fuente.

\[I_d = k_d \odot i_d \, \max(\mathbf{N}\cdot\mathbf{L},\ 0)\]
  • $\mathbf{N}\cdot\mathbf{L} = \cos\theta$ — porque los dos son unitarios.
  • Independiente de la cámara: un punto difuso se ve igual desde cualquier lado.
  • Modela superficies mates: papel, tiza, madera sin lustrar, piedra.
4 · El modelo de Phong

Componente difusa

Por qué el $\max(\cdot,\ 0)$ no es opcional. Pasados los 90°, el producto escalar $\mathbf{N}\cdot\mathbf{L}$ se vuelve negativo: la luz está detrás de la superficie. Sin el recorte, la fórmula no devuelve «nada de luz», devuelve luz negativa, y como los términos se suman, esa cara le resta a lo que aportan las otras fuentes y el ambiente. El $\max(\cdot,\ 0)$ pone por escrito lo que pasa en la realidad: una cara que no ve a la fuente no recibe nada de ella, y nada es cero.

Escribirla sin el max

En la práctica el síntoma son manchas oscuras, o iluminación que atraviesa el objeto.

Dónde aparece en serio

Shirley aclara al margen que esto pasa sobre todo con normales interpoladas — o sea, con Phong shading, que es el tema del bloque 7. El bug nace acá y se manifiesta allá.

29 / 87
Interactiva
4 · El modelo de Phong

Componente especular

El brillo. El único término que depende de dónde estás parado.

\[I_s = k_s \odot i_s \, \max(\mathbf{R}\cdot\mathbf{V},\ 0)^{\alpha}\]
  • $\mathbf{R}\cdot\mathbf{V} = \cos\phi$ — cuánto se alinea el reflejo ideal con la mirada.
  • $\alpha$ — exponente de brillo. Controla qué tan angosto es el lóbulo.
  • También lleva $\max(\cdot,0)$, por la misma razón que la difusa.
  • Si movés la cámara, el brillo se mueve con vos.
30 / 87
Interactiva
4 · El modelo de Phong

α y $k_s$: los dos ejes del brillo

  • α bajo (5-20): material rugoso o mate. Brillo amplio y difuso.
  • α alto (100-1000): material pulido. Brillo chico e intenso.
  • $k_s$ no cambia el tamaño del brillo: cambia cuánto se refleja.
El orden importa

Es $\max(\mathbf{R}\cdot\mathbf{V}, 0)^{\alpha}$ y no $\max((\mathbf{R}\cdot\mathbf{V})^{\alpha}, 0)$. Con $\alpha$ par, elevar primero convierte los negativos en positivos y aparecen brillos en la cara oculta del objeto.

Regla de la variable única, aplicada

Las 16 se renderizan por separado, con la luz en la misma posición relativa. Cada fila cambia solo $k_s$; cada columna, solo α.

31 / 87
4 · El modelo de Phong

Blinn-Phong: por qué se te movió el brillo

Phong (1975) y Blinn (1976) no son el mismo modelo, aunque los motores llamen a los dos «Phong».

Phong
\[(\mathbf{R}\cdot\mathbf{V})^{\alpha}\]

1975Hay que calcular $\mathbf{R}$ en cada fragmento.

Blinn-Phong
\[(\mathbf{N}\cdot\mathbf{H})^{\beta}\]

1976Más barato, y mejor en ángulos rasantes.

El exponente no es el mismo

$2\psi = \phi$: el ángulo de Blinn-Phong es la mitad del de Phong. Con el mismo exponente, el brillo de Blinn-Phong sale más grande. Para un resultado comparable hace falta $\beta \approx 2\text{–}4\,\alpha$. Por eso al cambiar de modelo sin tocar shininess el brillo "se mueve".

32 / 87
4 · El modelo de Phong

La ecuación completa

Todo lo del bloque, en una línea.

\[I = k_a \odot i_a + f_{att}(d)\,\big[\, k_d \odot i_d \max(\mathbf{N}\cdot\mathbf{L},0) \;+\; k_s \odot i_s \max(\mathbf{R}\cdot\mathbf{V},0)^{\alpha} \,\big]\]
$k_a \odot i_a$
constante, fuera del corchete: no depende de la fuente
$f_{att}(d)$
modula los dos términos que sí dependen de la distancia
$\max(\mathbf{N}\cdot\mathbf{L},0)$
el recorte que evita luz negativa
$\max(\mathbf{R}\cdot\mathbf{V},0)^{\alpha}$
o $(\mathbf{N}\cdot\mathbf{H})^{\beta}$ si usás Blinn‑Phong
Por qué la ambiente queda afuera del corchete

Porque no viene de ninguna fuente en particular: es el sustituto de la luz indirecta de toda la escena. Atenuarla por la distancia a una fuente no tendría sentido.

Lo que esta ecuación no hace

No conserva energía, no depende del ángulo de Fresnel, no sabe de inter-reflexiones y no distingue rugosidad de brillo. Cada una de esas cuatro cosas es el capítulo de PBR.

33 / 87
4 · El modelo de Phong

Múltiples fuentes · metales y dieléctricos

¿Por qué el brillo del plástico es blanco y el del oro es dorado?

\[I = k_a \odot i_a + \sum_{m=1}^{M} f_{att}(d_m)\big[\,k_d \odot i_{m,d}\max(\mathbf{N}\cdot\mathbf{L}_m,0) + k_s \odot i_{m,s}\max(\mathbf{R}_m\cdot\mathbf{V},0)^{\alpha}\,\big]\]
  • Las contribuciones se suman: la luz es lineal.
  • La ambiente aparece una sola vez, fuera de la sumatoria.
  • Dieléctricos (plástico, madera, vidrio): $k_s$ es blanco. El brillo toma el color de la luz.
  • Conductores (metales): $k_s$ es coloreado por la reflectancia del metal, y $k_d \approx 0$.
Por qué el metal tiñe el brillo

En un dieléctrico, la luz que se refleja en la superficie no entra al material: sale sin teñirse. En un metal, los electrones libres absorben selectivamente según la longitud de onda, y lo que se refleja ya sale coloreado.

34 / 87
Interactiva
4 · El modelo de Phong

Probemos el material de Phong

La tetera, tres luces blancas fijas y todos los coeficientes de MeshPhongMaterial, sin mapas.

Three.js r160 · tetera: «The Utah Teapot», 3D graphics 101 (Sketchfab), CC BY-NC 4.035 / 87
Bloque 5

La superficie entra en la ecuación

Hasta acá, cada coeficiente de la ecuación era un número para todo el objeto. De acá en adelante, sale de una textura.

  • Flat, Gouraud y Phong shading — dónde se evalúa la fórmula que ya vimos.
  • Por qué hay que renormalizar la normal interpolada, y qué pasa si no.
  • Mapas: difuso, de reflexión (cube maps), de normales.
  • El sistema TBN y por qué el mapa de normales se ve violáceo.
  • Light maps: cómo se falsea la iluminación global de la slide 05.
5 · De Phong a la superficie

Dónde quedamos

La ecuación de la primera mitad, y las cinco constantes que ahora dejan de serlo.

\[I = k_a i_a + f_{att}(d)\,\big[\,k_d\, i_d \max(\mathbf{N}\cdot\mathbf{L}, 0) + k_s\, i_s \max(\mathbf{R}\cdot\mathbf{V},0)^{\alpha}\,\big]\]
  • Cada $k$ era un valor para todo el objeto.
  • Cada uno puede pasar a ser un valor por fragmento, leído de una textura.
  • La ecuación no cambia. Cambia de dónde salen sus números.
6 · Las normales

La normal como atributo de vértice

La normal no es una propiedad de la superficie: es un número guardado por vértice.

  • Cada vértice lleva posición, normal y UV en el mismo buffer.
  • El fragment shader no ve la malla: ve lo que la GPU interpoló entre esos números.
  • Por eso dos mallas idénticas pueden sombrearse distinto: lo que cambia son los atributos.
En Three.js

BufferGeometry guarda cada atributo en su propio BufferAttribute: position, normal, uv. computeVertexNormals() rellena normal promediando las caras vecinas.

6 · Las normales

¿En qué espacio se calcula la iluminación?

  • Objeto → mundo → vista: tres sistemas de coordenadas encadenados.
  • $\mathbf{N}\cdot\mathbf{L}$ sólo tiene sentido si los dos están en el mismo.
  • Convención del curso: iluminación en espacio de mundo. Es la de Three.js.
Por qué importa el sistema, no sólo el espacio

Shirley lo dice textualmente: «It is important to choose a coordinate system that is orthonormal when viewed in world space, because shading equations depend on angles between vectors». Si la base no es ortonormal, los ángulos se deforman aunque todo esté «en el mismo espacio».

6 · Las normales

La matriz normal

Una normal es una dirección, con $w = 0$: la traslación no la mueve, así que sólo cuenta el bloque $3\times3$ de $\mathbf{M}$. Multiplicada como si fuera un punto, con $w = 1$, la traslación la inclina. Con rotación o escalado uniforme, $\mathbf{M}$ alcanza. Con escalado anisotrópico, $\mathbf{M}$ inclina las normales y dejan de ser perpendiculares; la inversa transpuesta las mantiene perpendiculares, pero cambia su largo: por eso siempre se renormaliza.

\[\mathbf{N}' = \operatorname{normalize}\!\big((\mathbf{M}_{3\times3}^{-1})^{T}\,\mathbf{N}\big)\]
6 · Las normales

Una normal por cara, o una por vértice

  • Por cara: una normal perpendicular a cada triángulo.
  • Por vértice: el promedio normalizado de las caras que lo comparten.
  • No elegimos todavía ningún algoritmo de sombreado. Eso viene en el bloque 7.
Qué quiere decir «normal por cara»

En la GPU la normal es siempre un atributo de vértice. «Por cara» quiere decir que los tres vértices del triángulo llevan la misma normal: la perpendicular a la cara. Como dos triángulos vecinos necesitan normales distintas en la esquina que comparten, ese vértice se duplica: la misma posición, dos normales.

La distinción que se pierde siempre

«Facetado» y «suave» describen el resultado. Lo que lo produce puede ser la asignación de normales o el algoritmo de sombreado. Son dos palancas distintas y conviene no confundirlas.

7 · Algoritmos de sombreado

Modelo ≠ algoritmo, otra vez

El modelo dice qué se calcula. El algoritmo dice dónde se calcula.

  • Modelo de iluminación: Lambert, Phong, Blinn-Phong… la fórmula.
  • Algoritmo de sombreado: flat, Gouraud, Phong shading… la frecuencia de evaluación.
  • Nueve combinaciones, todas válidas. Three.js usa Blinn-Phong + por fragmento.
La trampa del nombre

«Phong» nombra dos cosas distintas: el modelo de reflexión (1975) y el algoritmo de interpolación de normales. Shirley lo señala expresamente: llamar Phong shading al sombreado por fragmento «is confusing».

7 · Algoritmos de sombreado

Flat shading

Una evaluación por cara. El resultado es constante en todo el triángulo.

  • Se evalúa la ecuación una vez por polígono, con la normal de la cara.
  • Es el más barato de los tres y el único que muestra la malla tal cual es.
  • Correcto para superficies que realmente son planas: un cubo, un cristal tallado.
En Three.js

material.flatShading = true. Ojo: hay documentación vieja que habla de una propiedad shading con THREE.FlatShading — esa API se eliminó en r72.

7 · Algoritmos de sombreado

Gouraud shading: se interpola el color

Se evalúa en los vértices y el rasterizador interpola el resultado.

  • Tres evaluaciones por triángulo, sin importar cuántos píxeles cubra.
  • Lo que se interpola es el color ya calculado, no la normal.
  • Fue el estándar durante veinte años, y sigue siendo lo correcto en hardware limitado.
Dónde se evalúa

En el vertex shader. Por eso Gouraud es barato: el costo escala con la cantidad de vértices, no con la de píxeles.

7 · Algoritmos de sombreado

Bandas de Mach: por qué las vemos

El facetado se ve peor de lo que es, y la culpa es de la retina.

  • En un salto de intensidad, el ojo exagera el contraste a los dos lados.
  • La causa es la inhibición lateral: cada receptor resta el promedio de sus vecinos.
  • No está en la imagen. Está en el observador.
Qué implica para nosotros

Cualquier discontinuidad de intensidad va a leerse más fuerte de lo que la calculamos. Es la razón por la que flat shading resulta tan desagradable, y por la que Gouraud fue una mejora tan grande.

7 · Algoritmos de sombreado

El defecto grave de Gouraud

  • Con el máximo especular sobre un vértice: el brillo aparece, pero deformado y del tamaño del triángulo.
  • Con el máximo en el medio del triángulo: el brillo desaparece por completo.
  • Al mover la luz, alterna entre las dos cosas: parpadea.
Por qué esto mata a Gouraud para materiales brillantes

Para que Gouraud funcione con brillos hay que subdividir hasta que cada triángulo sea del tamaño del brillo. Shirley lo dice textualmente.

Gouraud · máximo sobre un vértice
Phong · máximo sobre un vértice
Gouraud · máximo en el medio
Phong · máximo en el medio
7 · Algoritmos de sombreado

Phong shading: se interpolan las normales

Se interpola la normal y la ecuación se evalúa después, una vez por fragmento.

  • Lo que viaja del vertex al fragment shader es la normal, no el color.
  • La ecuación completa se evalúa por píxel cubierto.
  • Es lo que hace hoy cualquier material de Three.js que responda a la luz.
El nombre es desafortunado

Se lo suele llamar per-fragment shading, que describe mejor lo que hace. «Phong shading» viene del mismo autor que el modelo de Phong, pero es una cosa distinta.

7 · Algoritmos de sombreado

La normal interpolada se acorta

El promedio de dos vectores unitarios no es unitario.

  • La interpolación es lineal; la superficie de los vectores unitarios es una esfera.
  • El resultado cae dentro de la esfera: es más corto.
  • Hay igualdad sólo si $\mathbf{N}_1$ y $\mathbf{N}_2$ son paralelos, o sea en las zonas planas.
\[\left\|\frac{\mathbf{N}_1 + \mathbf{N}_2}{2}\right\| = \cos\!\left(\frac{\theta}{2}\right) \le 1\]
Si falta el normalize()

$\mathbf{N}\cdot\mathbf{L}$ deja de ser un coseno y la difusa se apaga en el medio de cada cara. La especular se apaga mucho más, porque el factor acortado va elevado a $\alpha$.

7 · Algoritmos de sombreado

Los tres, lado a lado

Flat
Gouraud
Phong
  • Flat: facetas planas, brillo con forma de polígono.
  • Gouraud: silueta suave, pero el brillo se derrite.
  • Phong: silueta igual de suave y el brillo redondo, del tamaño correcto.
La silueta no cambia nunca

Los tres tienen el mismo contorno poligonal. Ningún algoritmo de sombreado agrega geometría: eso queda para el bloque 11.

8 · La textura entra en la ecuación

Un mapa difuso es $k_d$ por fragmento

El mapa difuso
  • A la izquierda, $k_d$ es una constante para todo el objeto.
  • A la derecha, $k_d$ se lee de una textura en cada fragmento.
  • El resto de la ecuación no se entera. Misma malla, misma luz, mismo shader.
$k_d$ constante
Con mapa difuso
La frase que encuadra la segunda mitad

Shirley lo dice así: «each time shading is computed, we read one of the values used in the shading computation —the diffuse color, for instance— from a texture instead of using the attribute values that are attached to the geometry».

8 · La textura entra en la ecuación

Un mapa especular es $k_s$ por fragmento

El mapa especular · huellas
  • El mapa escala $k_s$ en cada fragmento: blanco es pulido, negro es mate.
  • Sólo se ve donde hay brillo. Fuera del reflejo, la esfera es idéntica.
  • Si la luz se mueve, el brillo encuentra otras huellas.
$k_s$ constante
Con mapa especular
Otra luz · otras huellas
En Three.js

specularMap existe en MeshPhongMaterial, MeshLambertMaterial y MeshBasicMaterial, y se lee del canal R. En Phong escala el brillo especular y también el reflejo del envMap; en Lambert y Basic, sólo el reflejo. MeshStandardMaterial no lo tiene: ahí el equivalente es el roughnessMap.

Verificado contra el código de Three.js r160: specularmap_fragment, lights_phong_pars_fragment y envmap_fragment51 / 87
8 · La textura entra en la ecuación

Color o datos: la única regla de espacio de color que nos toca

  • Lo que representa color —difuso, albedo, emisivo— se carga como sRGB.
  • Lo que representa datos —normales, rugosidad, altura, AO— se carga lineal.
  • Confundirlos falla en los dos sentidos: un mapa de color cargado lineal sale lavado; un normal map cargado como sRGB tuerce las normales.
En Three.js

textura.colorSpace = THREE.SRGBColorSpace para los mapas de color; THREE.NoColorSpace para los de datos. Documentación vieja usa encoding y sRGBEncoding: esa API quedó deprecada en r152.

Interactiva
9 · Mapas de entorno

Proyección equirectangular

Una sola imagen rectangular que cubre toda la esfera de direcciones.

El mapa equirectangular
  • El eje horizontal es la longitud ($0$ a $2\pi$), el vertical la latitud.
  • Es el formato en que vienen casi todos los HDRI que van a descargar.
  • Se deforma en los polos: ahí una fila entera de texels colapsa en un punto.
Reflejado en una esfera espejo
Por qué igual se usa

Una sola imagen, fácil de editar y de previsualizar. La GPU la convierte a cube map al cargarla, que es el formato que realmente muestrea.

Interactiva
9 · Mapas de entorno

Cube map: seis caras

Seis texturas cuadradas, una por cara de un cubo centrado en el objeto.

El cube map desplegado
  • Cada cara cubre 90° × 90° de la esfera de direcciones.
  • La distorsión es uniforme: no hay polos que se apelotonen.
Reflejado en una esfera espejo
En Three.js

CubeTextureLoader carga las seis imágenes en orden px, nx, py, ny, pz, nz. Con scene.background = cubeTexture además se ve el entorno detrás del objeto.

9 · Mapas de entorno

El límite: espejos perfectos

roughness 0.0
roughness 0.18
roughness 0.45
  • Un mapa de entorno devuelve un texel por dirección: un reflejo nítido.
  • Una superficie rugosa refleja muchas direcciones a la vez, y el reflejo se difumina.
  • Hacerlo bien es pre-filtrar el entorno por nivel de rugosidad. Eso es IBL, y es PBR.
Qué queda abierto

Los tres renders de al lado salen de un motor que sí hace ese pre-filtrado. Con el cube map crudo del pipeline clásico, sólo se puede hacer la primera columna. Volvemos sobre esto en el bloque 13.

10 · Normal maps y espacio tangente

Detalle sin geometría

El mapa de normales
  • La malla es idéntica en los dos: una esfera lisa.
  • A la derecha, la normal que entra en la ecuación se lee de un mapa.
  • El relieve es una ilusión del sombreado, no geometría.
Sin normal map
Con normal map
Por qué existe la técnica

Agregar el mismo detalle con geometría real costaría cientos de miles de triángulos. Un normal map cuesta una textura y una lectura por fragmento.

10 · Normal maps y espacio tangente

Qué guarda un normal map

Un vector por texel, empaquetado en los tres canales de color.

  • Una normal tiene componentes en $[-1, 1]$; un texel guarda valores en $[0, 1]$.
  • La codificación mapea un rango en el otro: es una transformación afín, nada más.
  • R, G y B no son color: son las componentes x, y, z de un vector.
\[RGB = 0.5\,\mathbf{N} + 0.5\]
El truco de lectura

Si un canal vale 128, esa componente vale 0. Si vale 255, vale +1. Si vale 0, vale −1. Con eso se puede leer un normal map a ojo.

10 · Normal maps y espacio tangente

Por qué se ve violáceo

El violeta no es un color elegido: es el valor de «no perturbar nada».

Sin perturbar, la normal en espacio tangente es $(0, 0, 1)$; codificada, $(128, 128, 255)$: ese violeta. Lo que se aparta del violeta está inclinado.

El bump map es un mapa de altura en grises: guarda cuánto sobresale cada punto. El normal map guarda hacia dónde se inclina, que es la derivada de esa altura.

Three.js acepta un bumpMap, pero no puede usarlo como normal: tiene que derivarla en cada fragmento, con más lecturas y un relieve más blando. Por eso la altura se convierte una vez a normal map, y se usa ese.

El normal map
El bump map (altura)
10 · Normal maps y espacio tangente

Decodificar: de $[0,1]$ a $[-1,1]$

El paso inverso de la codificación, y el que más se olvida.

  • Es la inversa exacta de $RGB = 0.5\,\mathbf{N} + 0.5$.
  • Sin este paso, todas las componentes quedan positivas.
  • El síntoma: el relieve se aplana y se corre hacia una esquina.
\[\mathbf{n} = 2\,\big(\text{texture}(mapa, uv).rgb\big) - 1\]
Por qué se olvida

Porque el resultado sigue siendo una imagen razonable. No hay error, no hay pantalla negra: sólo un relieve que se ve raro y nadie sabe por qué.

10 · Normal maps y espacio tangente

No hay desplazamiento de la superficie

La ilusión se cae en un lugar: el borde.

  • El normal map cambia la normal, no la posición de los vértices.
  • En el interior, el relieve convence. En la silueta, no hay nada que sobresalga.
  • Tampoco hay auto-sombra: un ladrillo no proyecta sombra sobre el de al lado.
Dónde deja de alcanzar

En objetos vistos de canto, en bordes contra el cielo, y en superficies con relieve profundo. Para eso está el bloque 11.

10 · Normal maps y espacio tangente

¿Respecto de qué eje apunta esa normal?

La pregunta que obliga a inventar todo lo que viene.

  • El texel dice $(0.6,\ 0,\ 0.8)$. ¿Hacia dónde es eso en el mundo?
  • Depende de cómo esté orientada la cara.
  • Hace falta un sistema de ejes propio de cada cara: el espacio tangente.
La alternativa que no funciona

Guardar la normal en coordenadas de mundo: la textura sólo serviría para esa superficie, sin poder repetirla, espejarla ni usarla en otro modelo.

10 · Normal maps y espacio tangente

El espacio tangente

Un sistema de coordenadas propio en cada punto de la superficie.

  • No es un espacio global: hay uno distinto en cada fragmento.
  • Está pegado a la superficie, y su eje principal se alinea con las UV.
  • El normal map guarda sus vectores en ese espacio, y por eso es reutilizable.
La consecuencia práctica

Una sola textura de ladrillos sirve para una pared, para una columna y para el piso. Si las normales estuvieran en coordenadas de mundo, harían falta tres texturas distintas.

10 · Normal maps y espacio tangente

La base TBN

Tres ejes ortonormales: tangente, bitangente y normal.

  • T — la dirección en que crece $u$. Va en el canal R.
  • B — la dirección en que crece $v$. Va en el canal G.
  • N — la normal de la cara. Va en el canal B.
  • Los tres forman una matriz que lleva del espacio tangente al de mundo.
El léxico de color no es decoración

Rojo = X = R, verde = Y = G, azul = Z = B. El color con que se dibuja cada eje en estos diagramas es el mismo canal donde se guarda su componente. Es la misma información dicha dos veces.

10 · Normal maps y espacio tangente

Bitangente, no binormal

El nombre correcto, y por qué el otro se usa igual.

  • «Binormal» viene del triedro de Frenet, que describe una curva.
  • En una superficie no hay una sola tangente: hay un plano de tangentes.
  • Por eso hacen falta dos, y las elige la parametrización UV.
Reconocer el préstamo

Three.js y buena parte de la industria dicen «binormal». Está mal usado, pero está tan instalado que conviene reconocerlo al leer código ajeno.

10 · Normal maps y espacio tangente

De dónde salen T y B

De los bordes del triángulo, y de cuánto cambian las UV a lo largo de ellos.

  • Dos ecuaciones vectoriales, dos incógnitas: se despeja.
  • Los $\Delta u$ y $\Delta v$ salen de las UV de los mismos tres vértices.
  • Por eso T y B dependen del desenrollado, no sólo de la forma de la malla.
\[\begin{aligned}\mathbf{E}_1 &= \Delta u_1\,\mathbf{T} + \Delta v_1\,\mathbf{B}\\ \mathbf{E}_2 &= \Delta u_2\,\mathbf{T} + \Delta v_2\,\mathbf{B}\end{aligned}\]
En Three.js

BufferGeometryUtils.computeTangents() hace exactamente esta cuenta y deja el resultado en el atributo tangent. Necesita que la geometría tenga uv; sin UV no hay tangente posible.

10 · Normal maps y espacio tangente

El signo de la bitangente

Con UV espejadas, el producto vectorial apunta para el lado equivocado.

  • Espejar UV es habitual: ahorra media textura en cualquier modelo simétrico.
  • En la mitad espejada, $\mathbf{B} = \mathbf{N} \times \mathbf{T}$ da la dirección contraria.
  • Por eso la tangente se guarda en un vec4, con $w = \pm 1$ como corrector.
Cómo se ve

El relieve aparece invertido en la mitad espejada: lo hundido sale y lo que sale se hunde. No rompe nada, no tira ningún error, y sólo pasa de un lado del modelo.

10 · Normal maps y espacio tangente

Componer la normal final

Las tres componentes del texel son los pesos de los tres ejes.

  • Es un cambio de base: del espacio tangente al de mundo.
  • Escrito como matriz, $\mathbf{N}' = TBN \cdot \mathbf{n}$, con $TBN$ armada por columnas.
  • Y hay dos maneras de hacerlo, con costos distintos.
\[\mathbf{N}' = N_x\,\mathbf{T} + N_y\,\mathbf{B} + N_z\,\mathbf{N}\]
La estrategia barata

Transformar $\mathbf{L}$ y $\mathbf{V}$ al espacio tangente en el vertex shader, con $TBN^T$, y hacer toda la iluminación ahí. Se pasan dos vectores por vértice en vez de una matriz por fragmento.

Interactiva
10 · Normal maps y espacio tangente

Normal maps: todo junto

80 triángulos. Elegí la capa, mové la luz y, con un clic, mirá un fragmento de cerca.

Three.js r160 · shader propio · ladrillos brick_wall_006 (Poly Haven, CC0)68 / 87
11 · Relieve: de la ilusión a la geometría

La sombra delata el relieve plano

Con luz rasante, un normal map no proyecta ninguna sombra. No tiene con qué.

  • El normal map perturba la normal, no la superficie: la malla sigue siendo un plano.
  • Un fragmento plano no puede taparle la luz a su vecino: no hay auto-sombra.
  • Tampoco hay sombra arrojada sobre el mortero, que es donde el ojo la busca.
Normal map · la superficie sigue plana
Geometría desplazada · aparece la sombra
Cuándo se nota

Con la luz de frente el normal map es indistinguible de la geometría. El error aparece cuando la luz se vuelve rasante: ahí la sombra que falta es más informativa que el sombreado que sí está.

11 · Relieve: de la ilusión a la geometría

Displacement: mover los vértices de verdad

El mismo mapa de altura, pero aplicado a la posición en vez de a la normal.

  • Mismo mapa de altura que alimenta al normal map; cambia dónde se usa.
  • Va en el vertex shader: silueta, auto-sombra y paralaje reales.
  • El costo no es la textura: es la densidad de malla.
\[P' = P + h(u,v)\,\mathbf{N}\]
24×24 segmentos · el relieve se rompe
512×512 segmentos · el relieve cierra
La regla práctica

El relieve representable está limitado por la separación entre vértices. Con la malla más gruesa que el detalle del mapa no sale un relieve suave: sale uno roto.

11 · Relieve: de la ilusión a la geometría

Parallax: desplazar la UV según la vista

El término medio: sin tocar un vértice, pero con paralaje de verdad.

  • El rayo del ojo toca el polígono en A. Desde ahí se marcha por el mapa de altura, en espacio tangente, hasta cruzar el relieve en B.
  • La distancia de A a B en la textura es el $\Delta uv$: el fragmento A se pinta con la textura de B.
  • Da paralaje y auto-oclusión. No da silueta ni sombra arrojada.
Motivación: Marschner & Shirley, §11.4.3, p. 280 — la técnica no está en la bibliografía de la carpeta71 / 87
11 · Relieve: de la ilusión a la geometría

Los tres, comparados

Misma pared, misma luz, misma cámara. Lo único que cambia es la técnica.

Normal map · 2 triángulos · sin paralaje
Parallax · 2 triángulos · sin silueta
Displacement · ~500 000 triángulos · real
12 · Light maps, alfa y orden

Light maps: guardar lo que no se puede calcular

El light map: las cinco caras desplegadas
Sólo la luz directa
Con el light map
  • Cada texel guarda la luz que llega a un punto de la superficie: el resultado, no la fórmula.
  • Acá vuelve la iluminación global de la slide 05, pero precalculada.
  • Sólo sirve para lo que no se mueve: la geometría y las luces quedan congeladas.
Por qué sólo el decorado

El mapa vale para la geometría de fondo, que está quieta. Un personaje que camina no puede llevar su iluminación horneada: se le aplica de otra manera.

12 · Light maps, alfa y orden

El segundo canal UV

Un light map no puede usar el mismo desenrollado que el mapa de color.

  • UV1 puede repetirse y superponerse: el mismo ladrillo sirve en veinte paredes.
  • UV2 tiene que ser inyectivo: cada punto de la superficie, su propio texel.
  • Si dos puntos comparten texel, comparten la luz que se horneó ahí. Y no es la misma.
En Three.js

BufferGeometry guarda el segundo juego en el atributo uv1, y una textura lo elige con textura.channel = 1. En material anterior a r155 aparece como uv2: se renombró, y es una fuente frecuente de confusión.

Verificado contra el código de Three.js r162 (`getChannel`) — el tema no está en los libros de la carpeta74 / 87
Interactiva
12 · Light maps, alfa y orden

Luz horneada: un dormitorio con lightmaps

Three.js r160 · horneado: Blender 5.1, Cycles · texturas y HDRI grasslands_sunset: Poly Haven (CC0)75 / 87
12 · Light maps, alfa y orden

Alpha maps: opacidad por fragmento

El mapa de alfa
Sin alpha map: la malla es un cuadrado
Con alpha map
  • El mapa de alfa es dato, no color: su único canal es la opacidad.
  • Recorta la silueta por fragmento, sin tocar un solo vértice.
  • Es lo que hace que un árbol tenga hojas y no cientos de miles de triángulos.
En Three.js

alphaMap necesita transparent: true. Con alphaTest en un valor entre 0 y 1, todo fragmento con alfa menor no se dibuja.

12 · Light maps, alfa y orden

discard o blending

Dos maneras de usar el alfa, con costos y problemas distintos.

  • Alpha test: binario y barato. El fragmento queda en el z-buffer y no depende del orden.
  • Blending: medio tono real, pero hay que ordenar y el objeto no queda en el z-buffer.
  • La regla práctica: follaje y rejas con alpha test; vidrio y humo con blending.
Por qué el alpha test es más cómodo de lo que parece

Como escribe profundidad, un objeto con alpha test se comporta como uno opaco: se lo puede dibujar en cualquier orden y sigue tapando bien lo que tiene detrás. Es lo que hace que un bosque entero se pueda dibujar sin ordenar nada.

12 · Light maps, alfa y orden

El problema del orden

La misma escena, la misma cámara. Lo único que cambia es en qué orden se dibujan las tres capas.

  • La prueba de profundidad es conmutativa: con ella sola, el orden no importa.
  • Mezclar no lo es: a sobre b no da lo mismo que b sobre a.
  • Por eso lo translúcido se dibuja de atrás hacia adelante, y hay que ordenarlo en la aplicación.
De atrás hacia adelante
De adelante hacia atrás
Y no siempre se puede

Ordenar por objeto alcanza cuando los objetos no se atraviesan. Dos superficies translúcidas que se cruzan no tienen un orden correcto: cualquiera de los dos está mal en parte de la pantalla. Ahí ya no hay solución dentro de este pipeline.

12 · Light maps, alfa y orden

Un objeto transparente solo: dos pasadas

Cuando no hay nada detrás contra qué mezclar, lo que falta son las caras de atrás del propio objeto.

  • Con una sola pasada se dibujan sólo las caras de adelante: el objeto se ve opaco.
  • Se dibuja dos veces: primero las de atrás, después las de adelante.
  • Es el mismo orden de siempre —de atrás hacia adelante— pero adentro de un solo objeto.
Una pasada: sólo las caras de adelante
Dos pasadas: atrás y después adelante
En Three.js

Dos mallas con la misma geometría: una con side: THREE.BackSide y renderOrder: 0, otra con side: THREE.FrontSide y renderOrder: 1. En WebGL crudo es la misma idea con gl.cullFace(gl.FRONT) y después gl.cullFace(gl.BACK).

13 · El puente a PBR

Ambient occlusion: el parche del parche

El mapa de AO
Ambiente constante
Ambiente × AO
  • El AO map guarda, por texel, cuánto del cielo le tapa la geometría vecina.
  • Multiplica a la ambiente, no se suma: es un factor entre 0 y 1.
  • Va en el segundo canal UV, igual que el light map, y por el mismo motivo.
No es una sombra

Una sombra depende de dónde está la luz; el AO no. Es una propiedad de la forma del objeto, y por eso se puede hornear una sola vez y sirve para cualquier iluminación.

13 · El puente a PBR

Rugosidad: el brillo deja de ser un número

roughness 0.05
roughness 0.25
roughness 0.55
roughness 0.90
  • La superficie está cubierta de microfacetas; la rugosidad dice cuánto se desvían.
  • Rugosidad 0, reflejo especular; rugosidad 1, difuso. Y puede ser un mapa.
Por qué es mejor que el exponente

El exponente de Phong no tenía ni unidades ni límites: 30 y 300 son igual de arbitrarios. La rugosidad va de 0 a 1 y significa lo mismo en cualquier motor.

13 · El puente a PBR

Metal o dieléctrico

metalness 0 · dieléctrico
metalness 0.5 · ningún material real
metalness 1 · metal
  • Un dieléctrico refleja sin teñir: el brillo tiene el color de la luz, no el del material.
  • Un metal absorbe lo que entra y tiñe su reflejo con su propio color. Y no tiene difuso.
  • Por eso metalness es casi binario: 0 o 1. Los valores del medio no son ningún material real.
El valor por omisión engaña

El libro dice que metalness y roughness valen 0.5 por omisión. En r162 valen 0 y 1, verificado en el código. Un 0.5 heredado de un ejemplo viejo es un material que no existe.

13 · El puente a PBR

Emissive: superficie que no depende de la luz

Un término que se suma al final y al que ninguna luz afecta.

  • Color puro sumado al final: ninguna luz lo modifica.
  • No ilumina a los vecinos: la otra esfera y el piso no cambian.
  • Para que ilumine hace falta una luz real, o bloom en post.
emissive apagado
emissive encendido · el vecino no cambia
En Three.js

emissive es un color —negro por omisión— y emissiveIntensity su intensidad. El libro es explícito: «It doesn't act as a light source».

13 · El puente a PBR

De Phong a PBR, término por término

Qué le pasa a cada término al pasar a un modelo físico.

14 · Cierre

El mapa de los mapas

Síntesis del capítulo · las miniaturas son las figuras de cada slide85 / 87
Interactiva
14 · Cierre

Los mapas del capítulo, en una escena real

Three.js r160 · texturas y cielo 360°: Poly Haven y ambientCG (CC0) · cuadro: Hokusai, «La gran ola de Kanagawa» (dominio público)86 / 87
14 · Cierre

Referencias · qué viene después

Todo lo que dice esta presentación está verificado contra estas obras, página por página.

  • Hughes, J. et al., Computer Graphics: Principles and Practice, 3.ª ed.Cap. 26 «Light», pp. 669-712 · Cap. 27 «Materials and Scattering», Ec. 27.20-21, p. 722 · microfacetas p. 726 · conductores p. 682 · oclusión ambiental p. 742
  • Marschner, S. & Shirley, P., Fundamentals of Computer Graphics, 5.ª ed.Cap. 5 «Surface Shading», pp. 99-106 · §9.2, p. 197 · §11.4.3, p. 280 · Cap. 22, pp. 630 y 641 · §17.13, pp. 486-487
  • Angel, E. & Shreiner, D., Interactive Computer Graphics with WebGL, 7.ª ed.Cap. 6 «Lighting and Shading», pp. 277-302 · §7.10.5, p. 371
  • Ghayour, F. & Cantor, D., Real-Time 3D Graphics with WebGL 2, 2.ª ed.Cap. 6: profundidad, blending y face culling
  • Dirksen, J., Learn Three.js, 4.ª ed.pp. 105-107, 125-131 — nombres y propiedades de los materiales
  • Phong, B. T., Illumination for Computer Generated PicturesCommunications of the ACM 18(6), 1975, pp. 311-317
  • LearnOpenGL, Basic Lighting · Light Casterslearnopengl.com — CC BY-NC 4.0
Qué viene después, y qué no estaba en los libros

Sigue PBR: la ecuación de rendering, el modelo de microfacetas, Fresnel e iluminación basada en imagen. Tres cosas de este capítulo no aparecen en ninguna de las cinco obras —parallax occlusion mapping, el segundo canal UV y el AO fuera de Hughes— y están verificadas contra el código de Three.js r162 o contra la figura generada. Cuando una fuente no alcanza, se dice.

fuentes/indice-libros.txt · ediciones y desfasajes verificados abriendo cada PDF87 / 87