← CC2018

Shaders

Semestre 02, 2026

Usos de los shaders

La GPU no trae efectos integrados. Cada efecto visual de una escena es un shader distinto o una variante de uno.

Animar geometría en la GPU, como olas, telas y vegetación.
Decidir dónde y con qué detalle se calcula la iluminación.
Combinar varias texturas en un mismo material.
Generar terreno, nubes, agua y fuego sin imágenes.
Producir estilos no realistas, como el de una caricatura.
Procesar la imagen terminada, como desenfoque o bordes.

Un programa por efecto

Principio

Un motor no usa un único shader. Cada material, cada tipo de luz y cada pase de render requiere su propio programa, y las combinaciones de opciones multiplican el número de variantes.

Un mismo material se compila en una variante con sombras y otra sin ellas, en una con normal map y otra sin él.
Un motor comercial compila miles de variantes. Compilarlas durante la partida produce pausas visibles entre cuadros, conocidas como shader stutter.

Lenguajes de shaders

LenguajeAPIPlataforma
GLSLOpenGL, VulkanMultiplataforma
HLSLDirectXWindows y Xbox
MSLMetalmacOS e iOS
WGSLWebGPUNavegador
Todos comparten el mismo modelo, con tipos vectoriales y matriciales nativos y un punto de entrada por etapa. El driver compila el programa en tiempo de ejecución para la GPU instalada.

Etapas programables adicionales

Además del vertex y el fragment shader, el pipeline moderno admite tres tipos de shader más.

ShaderSe ejecuta una vez porProduce
TessellationParche de la mallaVértices nuevos que subdividen el parche
GeometryPrimitivaCero o más primitivas nuevas
ComputeElemento de trabajoDatos arbitrarios en buffers, fuera del pipeline gráfico

Programa de shaders

Definición

Unidad que resulta de compilar y enlazar los shaders de cada etapa. El vertex shader y el fragment shader son obligatorios, y el resto de etapas es opcional.

Las salidas del vertex shader deben coincidir en nombre y tipo con las entradas del fragment shader, o el enlace falla.
Cambiar de material suele implicar cambiar de programa, lo que tiene un costo en la CPU.

Ejecución en paralelo

Principio

Cada invocación de un shader es independiente de las demás. La GPU puede ejecutarlas en cualquier orden y al mismo tiempo, porque ninguna depende del resultado de otra.

Un fragmento no puede leer el color que calculó su vecino.
Un fragmento solo escribe en su propia posición de pantalla.
Una invocación no recuerda nada del cuadro anterior.

Warps

Definición

Grupo de invocaciones que la GPU ejecuta en bloque con una sola unidad de control. Todas ejecutan la misma instrucción al mismo tiempo, cada una con sus propios datos.

NVIDIA los llama warps y los forma con 32 invocaciones. AMD los llama wavefronts y usa 32 o 64.
Los fragmentos de un warp son vecinos en pantalla, porque así comparten datos de textura en caché.

Divergencia

Definición

Situación en la que las invocaciones de un mismo warp toman ramas distintas de una condición. El warp ejecuta una rama con las invocaciones de la otra desactivadas, y luego la otra.

$$ t_{warp} = t_{if} + t_{else} $$
Una condición que vale igual para todo el warp, como un uniform, no produce divergencia y no tiene costo extra.

La divergencia en vivo

Funciones de forma

Definición

Funciones matemáticas que todo lenguaje de shaders trae integradas para transformar un valor en otro sin usar condiciones. Son la herramienta básica para evitar la divergencia.

$$ \operatorname{step}(e, x) = \begin{cases} 0 & x < e \\ 1 & x \geq e \end{cases} \qquad \operatorname{mix}(a, b, t) = a\,(1 - t) + b\,t $$
El resultado de step multiplicado dentro de mix elige entre dos colores sin escribir un if.

Smoothstep

Definición

Transición suave entre cero y uno a lo largo del intervalo de \(e_0\) a \(e_1\), con derivada nula en los dos extremos.

$$ t = \operatorname{clamp}\!\left(\frac{x - e_0}{e_1 - e_0},\, 0,\, 1\right) \qquad \operatorname{smoothstep}(e_0, e_1, x) = t^2\,(3 - 2t) $$
Un borde hecho con step queda dentado. El mismo borde con smoothstep de uno o dos píxeles de ancho se ve suavizado.

Las funciones de forma en vivo

Modelos de sombreado

Definición

Estrategia que decide en qué punto de la superficie se evalúa la ecuación de iluminación y cómo se reparte el resultado sobre el resto del triángulo.

La ecuación de iluminación es la misma en los tres modelos, que son flat, Gouraud y Phong shading.
Phong shading es un modelo de sombreado. El modelo de reflexión de Phong, visto en Materiales, es la ecuación. Comparten el autor, no el concepto.

Flat shading

Definición

La iluminación se evalúa una vez por cara con la normal de la cara, y todos los fragmentos del triángulo reciben ese mismo color.

Es el modelo más barato, con una evaluación por triángulo.
Las facetas quedan visibles, lo que sirve para un estilo low poly y no para superficies curvas.

Gouraud shading

Definición

La iluminación se evalúa en el vertex shader con la normal de cada vértice, y la rasterización interpola los tres colores resultantes sobre el triángulo.

Elimina las facetas con un costo de una evaluación por vértice.
Un brillo especular que cae en el interior de un triángulo se pierde, porque ningún vértice lo registra.

Phong shading

Definición

La rasterización interpola las normales de los vértices, y el fragment shader evalúa la iluminación en cada fragmento con su normal interpolada.

El brillo especular queda redondo y se desplaza de forma continua al mover la luz o la cámara.
La normal interpolada pierde su longitud unitaria y debe normalizarse otra vez en el fragment shader.

Comparación de modelos

ModeloEtapa de la luzLo que se interpolaEspecular
FlatUna vez por caraNadaPor cara
GouraudVertex shaderEl colorSe pierde o salta
PhongFragment shaderLa normalCorrecto
El costo depende del tamaño de los triángulos. Si un triángulo cubre menos de un píxel, evaluar por vértice resulta más caro que evaluar por fragmento.

Los tres modelos en vivo

Blinn-Phong

Definición

Variante del modelo de Phong que cambia solo la componente especular. Mide el brillo con el vector medio \(H\) entre la luz y la cámara, en lugar del rayo reflejado \(R\).

$$ I_s = k_s \max(0,\, N \cdot H)^{\alpha} \qquad H = \frac{L + V}{\lVert L + V \rVert} $$
Calcular \(H\) cuesta menos que reflejar \(L\), y el brillo no se corta en ángulos rasantes. Es el modelo por defecto del pipeline fijo de OpenGL.

Wrapping

Definición

Regla que decide qué texel devolver cuando la coordenada UV cae fuera del rango de cero a uno. Se configura por separado para cada eje.

ModoComportamiento
RepeatUsa la parte fraccionaria y repite la imagen.
Mirrored repeatRepite la imagen reflejada en cada repetición.
Clamp to edgeEstira el último texel del borde.
Clamp to borderDevuelve un color de borde fijo.

El wrapping en vivo

Filtrado

Definición

Regla que calcula el color cuando la coordenada no cae justo en el centro de un texel. Importa sobre todo en la magnificación, cuando un texel cubre varios píxeles.

Nearest: toma el texel más cercano. El resultado se ve pixelado.
Linear: mezcla los cuatro texels vecinos según la distancia.
$$ c = \operatorname{mix}\big(\operatorname{mix}(c_{00},\, c_{10},\, s),\; \operatorname{mix}(c_{01},\, c_{11},\, s),\; t\big) $$

El filtrado en vivo

Minificación y aliasing

Problema

Cuando la superficie se aleja, un solo píxel cubre muchos texels. Si el sampler toma una sola muestra, el color salta de un píxel al siguiente y aparecen patrones de moiré que parpadean al moverse.

Es el mismo fenómeno que el aliasing de las líneas, aplicado a la textura.
Promediar todos los texels de la huella en cada fragmento sería correcto, pero demasiado caro.

Mipmaps

Definición

Cadena de copias de la textura, cada una con la mitad del tamaño de la anterior y ya promediada. El sampler lee del nivel cuyo tamaño de texel se parece más a la huella del píxel.

$$ \lambda = \log_2 \rho \qquad 1 + \tfrac{1}{4} + \tfrac{1}{16} + \cdots = \tfrac{4}{3} $$
\(\rho\) es la cantidad de texels que cubre un píxel a lo largo de un eje.
La cadena completa ocupa un tercio más de memoria que la textura original.

Los mipmaps en vivo

Texturas como datos

Una textura guarda cuatro números por texel, y el shader decide qué significan.

Albedo: el color base del material.
Normal map: una normal por texel, codificada en RGB.
Height map: la altura de la superficie en cada punto.
Roughness: qué tan concentrado es el brillo especular.
Ambient occlusion: cuánta luz ambiente llega a cada rincón.
Máscara: qué zonas reciben un efecto y cuáles no.

Normal mapping

Definición

Técnica que reemplaza la normal interpolada por una leída de textura, para simular relieve sobre una superficie plana.

$$ N = \operatorname{normalize}\big(TBN\,(2c - 1)\big) $$
\(c\) es el color leído y \(TBN\) orienta la normal según la superficie.
La normal es perpendicular a la superficie en el punto

Shader procedural

Definición

Shader que calcula el color a partir de una fórmula, en lugar de leerlo de una imagen. La entrada suele ser la coordenada UV o la posición del fragmento.

Resolución ilimitada, porque se evalúa en cada fragmento.
No ocupa memoria de textura.
Se controla con uniforms y puede animarse con el tiempo.
Cuesta instrucciones en cada fragmento, cada cuadro.

La UV como lienzo

Principio

Multiplicar la UV por \(n\) y quedarse con la parte fraccionaria divide la superficie en \(n\) celdas que repiten el rango de cero a uno. Cualquier figura dibujada en una celda se repite en todas.

$$ f = \operatorname{fract}(n\,u) \qquad \text{franja} = \operatorname{step}(0.25,\, f) - \operatorname{step}(0.75,\, f) $$
Un tablero combina una franja en \(u\) con otra en \(v\), y un círculo compara la distancia al centro de la celda con un radio.

Los patrones en vivo

Ruido

Definición

Función pseudoaleatoria y continua, donde puntos cercanos devuelven valores parecidos. Es la base de nubes, terreno, mármol, fuego y agua.

Un número al azar por fragmento produce estática, porque vecinos cercanos no guardan relación.
El shader no tiene generador de aleatorios. Usa una función hash, que devuelve siempre el mismo valor para la misma entrada.

Value noise

Algoritmo

Se asigna un valor aleatorio a cada esquina de una cuadrícula y se interpola entre esquinas con smoothstep, para que no se noten los bordes de las celdas.

$$ r(x) = \operatorname{mix}\big(h(i),\; h(i + 1),\; \operatorname{smoothstep}(0, 1, f)\big) \qquad i = \lfloor x \rfloor,\; f = x - i $$
El ruido de Perlin asigna gradientes aleatorios en lugar de valores, y elimina el aspecto de bloques que deja el value noise.

Fractal Brownian Motion

Definición

Suma de varias capas de ruido, llamadas octavas, cada una con más frecuencia y menos amplitud que la anterior. Agrega detalle fino sobre la forma general.

$$ \operatorname{fbm}(p) = \sum_{k=0}^{N-1} g^{k}\; r\big(\ell^{k} p\big) $$
\(\ell\), la lacunaridad, multiplica la frecuencia, normalmente por 2.
\(g\), la ganancia, multiplica la amplitud, normalmente por 0.5.

El ruido en vivo

Ejemplo de planeta procedural

Enunciado

Se requiere sombrear una esfera para que parezca un planeta con océanos, costas, vegetación y montañas nevadas, sin usar ninguna textura.

1Altura
  • Evaluar un fBm sobre la posición del fragmento en la esfera.
2Rampa de color
  • Comparar la altura con el nivel del mar, un uniform, y elegir agua, arena, pasto, roca o nieve con smoothstep.
3Iluminación
  • Aplicar Lambert al terreno, brillo especular solo al agua y un halo de atmósfera en el borde.

El planeta en vivo

Desplazamiento de vértices

Definición

Efecto que mueve cada vértice antes de aplicar las matrices, en función de su posición, del tiempo o de una textura de altura.

Olas sobre una superficie de agua.
Banderas y telas movidas por el viento.
Pasto y hojas que se mecen.
Terreno levantado con un height map.

Ondas en la malla

Cada vértice se desplaza en la dirección de su normal según una onda que avanza con el tiempo, que llega como uniform.

$$ p' = p + n \cdot A \sin(\omega\, x + t) $$
\(A\) es la amplitud y \(\omega\) la frecuencia de la onda.
Al deformar la superficie, la normal original deja de ser válida. Hay que recalcularla con la derivada de la onda, o la iluminación no acompaña al movimiento.

El desplazamiento en vivo

El límite de resolución

Restricción

El vertex shader no agrega detalle. Una onda más fina que la separación entre vértices no se puede representar, sin importar la fórmula.

Subdividir la malla en la CPU, a costa de más vértices en memoria.
Usar un tessellation shader, que genera vértices nuevos en la GPU solo donde hacen falta.
Simular el detalle fino en el fragment shader con un normal map, sin mover la geometría.

Toon shading

Definición

Estilo que cuantiza la intensidad de la luz en pocas bandas planas, imitando el sombreado de una ilustración o de una caricatura.

$$ I_{toon} = \frac{\lfloor I \cdot n \rfloor}{n} $$
\(n\) es el número de bandas. El brillo especular se trata igual, con un solo umbral que lo vuelve una mancha de bordes duros.

Rim light y contorno

Rim light

Luz que aparece en el borde de la silueta, donde la normal es casi perpendicular a la dirección de la cámara.

$$ \text{rim} = \big(1 - \max(0,\, N \cdot V)\big)^{p} $$
El mismo producto \(N \cdot V\) sirve para un contorno, pintando de oscuro los fragmentos donde cae por debajo de un umbral.

El toon shading en vivo

Descarte de fragmentos

Definición

Instrucción discard del fragment shader, que abandona el fragmento sin escribir color ni profundidad. El píxel conserva lo que ya tenía.

Recortar hojas, rejas y cabello a partir del canal alfa de una textura.
Disolver un objeto comparando un ruido con un umbral que crece.
Un shader con discard impide que la GPU haga el depth test antes de ejecutarlo, así que se usa solo donde hace falta.

La disolución en vivo

Post-processing

Definición

Efectos que se aplican sobre la imagen ya renderizada y no sobre la geometría. La escena se dibuja en una textura y un segundo pase la procesa.

1Primer pase
  • Renderizar la escena en un framebuffer cuyo destino es una textura.
2Segundo pase
  • Dibujar un rectángulo que cubre la pantalla, con un fragment shader que lee esa textura y escribe el resultado.

Filtros por píxel

Cada fragmento solo necesita su propio color.

$$ Y = 0.2126\,R + 0.7152\,G + 0.0722\,B $$
Escala de grises: la luminancia \(Y\) en los tres canales.
Inversión: uno menos el color, canal por canal.
Viñeta: oscurecer según la distancia al centro.
Corrección de color: curvas por canal con una tabla.

Filtros por vecindad

El fragmento lee varios texels alrededor de su posición y los combina con un kernel de pesos.

$$ K_{blur} = \frac{1}{9}\begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix} \qquad G_x = \begin{bmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{bmatrix} $$
El desenfoque promedia la vecindad.
Sobel mide el cambio de luminancia y resalta los bordes.

El post-processing en vivo

Dónde vive cada efecto

EfectoEtapaSe ejecuta una vez por
Ondas y desplazamientoVertex shaderVértice
Gouraud shadingVertex shaderVértice
Phong shading y normal mappingFragment shaderFragmento
Patrones, ruido, toon y disoluciónFragment shaderFragmento
Filtrado y mipmapsUnidad de texturaLectura del sampler
Desenfoque y bordesSegundo pasePíxel de la imagen

Glosario de shaders

TérminoDefinición
Programa de shadersShaders de cada etapa compilados y enlazados como una unidad.
WarpGrupo de invocaciones que ejecuta la misma instrucción a la vez.
DivergenciaRamas distintas dentro de un warp, que se ejecutan una tras otra.
SmoothstepTransición suave entre cero y uno dentro de un intervalo.
Phong shadingIluminación evaluada por fragmento con la normal interpolada.
DiscardAbandono de un fragmento sin escribir color ni profundidad.

Glosario de texturas y procedurales

TérminoDefinición
SamplerUniform que da acceso a una textura con sus reglas de lectura.
WrappingRegla para coordenadas UV fuera del rango de cero a uno.
MipmapCadena de copias reducidas y promediadas de una textura.
Normal mapTextura que guarda una normal por texel.
RuidoFunción pseudoaleatoria continua.
fBmSuma de octavas de ruido con frecuencia creciente.