≡En resumen
- El Z-buffer es una estructura de datos: una tabla con un número de profundidad por cada píxel de la pantalla.
- Su tamaño coincide con la resolución de la imagen; a 1080p con 32 bits por píxel ocupa unos 8,3 MB.
- La precisión no es uniforme: se concentra cerca de la cámara y se pierde rápidamente con la distancia.
- Mover el plano cercano de la cámara hacia delante mejora la precisión mucho más que añadir bits.
- El proceso que lo usa para decidir qué se ve se llama Z-buffering o prueba de profundidad.
01 ¿Qué es el Z-buffer?
Conviene separar dos ideas que en español se mezclan a menudo: el Z-buffer es el dato (la memoria) y el Z-buffering es el algoritmo que lo lee y lo actualiza mientras se dibuja cada triángulo. Esta entrada se centra en la estructura: qué guarda, cuánto ocupa y por qué su precisión es la fuente de tantos errores visuales.
Junto al búfer de color (lo que ves en pantalla), el Z-buffer es uno de los búferes básicos de cualquier motor 3D, desde un videojuego hasta un visor de productos en una web o una app de realidad aumentada.
02 Origen: Straßer, Catmull y el año 1974
La idea de guardar una profundidad por píxel se describió dos veces el mismo año. El alemán Wolfgang Straßer la incluyó en su tesis doctoral de 1974 sobre algoritmos rápidos para dibujar objetos ocultos, y meses después Edwin Catmull presentó en la Universidad de Utah su tesis A Subdivision Algorithm for Computer Display of Curved Surfaces, donde también aparecen el mapeado de texturas y los parches bicúbicos.
La invención se atribuye casi siempre a Catmull, en parte por la influencia posterior de su carrera: cofundó Pixar en 1986 y en 2019 recibió el Premio Turing, junto a Pat Hanrahan, por su trabajo pionero en imágenes generadas por ordenador.
03 Qué guarda el búfer de profundidad y cuánto ocupa
Cada celda guarda un número normalizado, normalmente entre 0 (plano cercano de la cámara) y 1 (plano lejano). Antes de dibujar un fotograma el búfer se «limpia» con el valor más lejano, para que cualquier superficie que aparezca después quede delante.
Su resolución es la misma que la del búfer de color, así que su tamaño crece con la pantalla. Con 4 bytes por píxel (24 bits de profundidad más 8 de stencil, el formato más común):
| Resolución | Píxeles | Memoria del Z-buffer | Con antialiasing MSAA 4x |
|---|---|---|---|
| 1280 × 720 (HD) | 921.600 | ≈ 3,7 MB | ≈ 14,7 MB |
| 1920 × 1080 (Full HD) | 2.073.600 | ≈ 8,3 MB | ≈ 33,2 MB |
| 3840 × 2160 (4K) | 8.294.400 | ≈ 33,2 MB | ≈ 132,7 MB |
16 bits
65.536 niveles de profundidad. Ahorra memoria, pero en escenas grandes provoca parpadeos entre superficies cercanas. Se usa poco en 3D moderno.
24 bits + 8 de stencil
16,7 millones de niveles. Es el formato por defecto en la mayoría de GPU y navegadores; los 8 bits restantes sirven para máscaras (stencil).
32 bits en coma flotante
Más rango y, combinado con la técnica reverse-Z, una precisión casi uniforme en toda la escena. Habitual en motores de juego actuales.
8 bits
Existe en teoría, pero casi nunca se usa: 256 niveles son demasiado pocos para distinguir superficies.
04 Precisión del Z-buffer: por qué falla a lo lejos
En la proyección en perspectiva el valor que se guarda no es proporcional a la distancia real, sino a su inversa (1/z). El resultado es que la mayoría de los niveles disponibles se gastan en los primeros metros delante de la cámara y quedan muy pocos para el fondo. Por eso los errores de profundidad aparecen casi siempre en objetos lejanos.
Una estimación útil del error mínimo que el búfer puede distinguir a una distancia z, cuando el plano lejano está mucho más lejos que el cercano, es Δz ≈ z² / (n × 2^b), donde n es la distancia del plano cercano y b los bits del búfer.
| Distancia del objeto | 16 bits, cercano a 0,1 m | 24 bits, cercano a 0,1 m | 24 bits, cercano a 1 m |
|---|---|---|---|
| 10 m | ≈ 1,5 cm | ≈ 0,06 mm | ≈ 0,006 mm |
| 100 m | ≈ 1,5 m | ≈ 6 mm | ≈ 0,6 mm |
| 1.000 m | ≈ 150 m | ≈ 60 cm | ≈ 6 cm |
05 Z-buffer, W-buffer, reverse-Z y búfer logarítmico
Como la precisión desigual es el gran punto débil del Z-buffer clásico, han surgido variantes que cambian qué número se guarda o cómo se reparte:
| Variante | Qué guarda | Ventaja | Inconveniente |
|---|---|---|---|
| Z-buffer clásico | Profundidad proyectada (proporcional a 1/z) | Estándar en todo el hardware | Precisión muy concentrada cerca de la cámara |
| W-buffer | Distancia real en el espacio de la cámara | Precisión más uniforme | Soporte de hardware limitado y hoy poco usado |
| Reverse-Z | Profundidad invertida (cercano = 1, lejano = 0) en coma flotante de 32 bits | Compensa la curva 1/z con la de los números flotantes: precisión casi uniforme | Requiere búfer flotante y control del recorte (en WebGL, la extensión EXT_clip_control) |
| Búfer logarítmico | Profundidad en escala logarítmica escrita desde el shader | Escenas con escalas enormes (planetas, mapas) | Desactiva optimizaciones como la prueba temprana de fragmentos |
06 El Z-buffer en la web y en las apps
Si trabajas con WebGL, el búfer de profundidad se configura al crear el contexto. En three.js, la biblioteca de JavaScript más usada para 3D en navegador, el renderizador acepta tres opciones relacionadas: depth (activado por defecto, al menos 16 bits), logarithmicDepthBuffer y reversedDepthBuffer, ambas desactivadas por defecto.
En la práctica, un visor de producto, un recorrido virtual o un modelo capturado con un escáner 3D funcionan bien con el búfer por defecto si los planos de la cámara están bien ajustados. Cuando aparecen parpadeos, el origen suele ser una cámara con el plano cercano demasiado pegado.
Un visor 3D de una cocina con la cámara configurada con near = 0.01 y far = 10000 muestra la encimera «rayada» con el azulejo de detrás. Cambiando a near = 0.1 y far = 50, ajustados al tamaño real de la estancia, el problema desaparece sin tocar la geometría. Es el tipo de ajuste que se hace en cualquier proyecto de desarrollo web a medida con componentes 3D.
En móviles la memoria y el ancho de banda son más escasos, así que los motores nativos aprovechan técnicas como el Z-buffer jerárquico o descartar fragmentos ocultos antes de colorearlos. Si tu empresa de desarrollo de aplicaciones trabaja con 3D, pregunta cómo gestiona la profundidad en gamas bajas de Android.
07 Z-buffer vs Z-buffering vs stencil buffer
| Término | Qué es | Pregunta que responde |
|---|---|---|
| Z-buffer | Estructura de datos: memoria con una profundidad por píxel | ¿A qué distancia está lo que se ve en este píxel? |
| Z-buffering | Algoritmo o prueba de profundidad que usa el Z-buffer | ¿Dibujo este fragmento o queda tapado? |
| Stencil buffer | Búfer de máscara, a menudo compartiendo los 32 bits con el Z-buffer | ¿Este píxel está dentro de la zona que quiero pintar? |
Preguntas frecuentes sobre Z-buffer
Es una tabla en la memoria de la tarjeta gráfica con un número de profundidad por píxel. Sirve para saber qué objeto está delante en cada punto de la imagen.
Se refiere al eje Z, el que apunta hacia el fondo de la escena, perpendicular a la pantalla. X e Y marcan la posición horizontal y vertical del píxel.
Lo habitual son 24 bits de profundidad (con 8 de stencil en la misma palabra de 32 bits). También existen formatos de 16 bits y de 32 bits en coma flotante.
Se atribuye a Edwin Catmull, que lo describió en su tesis de 1974 en la Universidad de Utah, aunque Wolfgang Straßer publicó la misma idea en su tesis unos meses antes.
Depende de la resolución: con 4 bytes por píxel, unos 8,3 MB a 1920 × 1080 y unos 33 MB en 4K, multiplicado por las muestras si usas antialiasing MSAA.
Porque en perspectiva guarda un valor proporcional a 1/z, que reparte casi todos los niveles cerca de la cámara. A lo lejos, dos superficies próximas acaban con el mismo valor.
El Z-buffer es la memoria donde se guardan las profundidades; el Z-buffering es el algoritmo que las compara para decidir qué se dibuja.
Fuentes consultadas
Sobre el autor
Germán Gutiérrez
Development Manager en appyweb
Dirige el equipo de desarrollo de appyweb: aplicaciones web y móviles, SaaS, integraciones y arquitectura de software.
Ver perfil en LinkedIn ↗