Empaquetado de atlas de sprites: márgenes, potencias de dos y filtración

Un atlas de sprites parece una idea sencilla —poner todos los sprites en una gran textura en lugar de muchos archivos pequeños—, pero los detalles del empaquetado determinan si tu juego se renderiza con limpieza o desarrolla bordes tenues de color en cada sprite. Aquí explicamos qué hace realmente un atlas, por qué los colores se filtran en las uniones y qué ajustes concretos lo evitan.

Por qué existen atlas: llamadas de dibujo

Cada vez que una GPU pasa de dibujar con una textura a hacerlo con otra, el cambio tiene un coste: conceptualmente, una nueva «llamada de dibujo». Una escena con cincuenta sprites con texturas individuales, dibujados de forma ingenua, puede implicar cincuenta llamadas separadas aunque todos los sprites sean diminutos. En móviles en particular, ese coste se acumula lo bastante rápido como para afectar a la tasa de fotogramas mucho antes de que la GPU haga una cantidad significativa de trabajo real de píxeles.

Un atlas de sprites evita esto reuniendo muchos sprites en una textura compartida. Mientras todo lo dibujado en un lote tome muestras de la misma textura, el renderizador puede combinar esos dibujos en muchas menos llamadas: en el mejor caso, una llamada de dibujo para todos los sprites que comparten atlas y material. Por eso los atlas importan más en juegos con muchos sprites pequeños que se redibujan con frecuencia —efectos de partículas, iconos de interfaz, conjuntos de piezas— que para unas pocas imágenes grandes de fondo, donde el número de llamadas de dibujo nunca fue el cuello de botella.

Empaquetado: encajar sprites en una textura

Dado un conjunto de sprites de tamaños diferentes, colocarlos en una textura con el mínimo espacio desperdiciado es una variante del clásico problema de empaquetado. La mayoría de las herramientas de atlas utilizan una variante de uno de estos dos métodos:

  • Empaquetado por filas: coloca sprites de izquierda a derecha en una fila o «estante» hasta que no cabe otro y abre una debajo. Simple y rápido, pero desperdicia si varían mucho las alturas.
  • Rectángulos máximos / empaquetado guillotina: el empaquetador registra rectángulos libres tras cada colocación y encaja el siguiente en el mejor espacio, dividiéndolos. Es más denso y exige más cálculo; habitual en TexturePacker, Sprite Atlas de Unity y Godot salvo cantidades triviales.

Algunos empaquetadores permiten otra optimización: girar un sprite 90 grados para encajarlo en un hueco estrecho. Aprovecha mejor el espacio, pero complica el renderizado porque las coordenadas UV deben considerar el giro. Suele ser opcional, no predeterminado.

No necesitas implementarlo: las herramientas del motor y los empaquetadores especializados lo resuelven. Conviene entender la tensión entre densidad y relleno: apretar reduce espacio desperdiciado, pero la separación evita la contaminación descrita abajo. Un empaquetador demasiado agresivo puede reintroducir fallos visuales por ahorrar unos puntos porcentuales de textura.

Filtración de texturas: qué es y por qué ocurre

Filtración de texturas ocurre cuando el borde muestra color del sprite vecino del atlas: una línea ajena a su ilustración en uno o varios lados. Es un fallo común de atlas con dos causas que suelen confundirse.

Filtración de colores por el filtrado. Al dibujar a una escala distinta de 1:1 o posición no alineada, el filtro GPU muestrea texeles vecinos, no solo el más cercano. Incluso con filtro puntual, el muestreo y mipmaps pueden salir ligeramente del rectángulo UV. Si al lado hay otro sprite, entra su color.

Filtración por mipmaps. Los mipmaps son versiones reducidas de la textura completa que se usan cuando un sprite se dibuja pequeño. Al generarlos se mezclan bloques de la textura de resolución completa, por lo que los colores de un sprite pueden contaminar el nivel mip del vecino antes incluso de dibujarlos. Por eso la contaminación a veces solo aparece a distancia o a pequeña escala y desaparece al ampliar.

Ambas causas se remontan a la misma condición: dos sprites sin relación colocados inmediatamente uno junto al otro en el atlas, sin nada entre ellos que absorba el error de muestreo.

Izquierda: sprites empaquetados borde con borde en un atlas, con ampliaciones que muestran uniones de color incorrecto. Derecha: los mismos sprites separados por márgenes transparentes, con bordes limpios en las ampliaciones
Los detalles ampliados muestran todo el problema. Si los sprites están pegados, un muestreo medio texel más allá del límite cae en el sprite vecino y arrastra su color por la junta.

Corregir la filtración: márgenes y extrusión

La solución estándar es margen — deja píxeles transparentes o de borde duplicado entre sprites para que el muestreo caiga en el hueco, no en el vecino. Uno o dos suelen bastar a resolución nativa; con ampliación o mipmaps, más relleno da margen de error.

El relleno transparente evita filtraciones del sprite vecino, pero crea un problema menor: en el borde, el filtro puede mezclar el color del sprite con ese relleno, causando oscurecimiento o halos leves en vez de un borde limpio. Extrusión (a veces llamada extensión de bordes) lo soluciona rellenando el margen con una copia de los píxeles del borde del propio sprite, extendida hacia fuera, en vez de dejarlo transparente. El problema de los vecinos se resuelve igual: sigue habiendo un espacio entre sprites distintos, pero el borde del propio sprite se mezcla con más píxeles de sí mismo en lugar de con transparencia vacía.

La mayoría de las herramientas de atlas —TexturePacker, el empaquetador Sprite Atlas de Unity y la exportación de Godot— ofrecen tamaño de relleno y activación de extrusión en sus ajustes. Rara vez conviene dejar el relleno en cero: uno o dos píxeles por borde cuestan poca textura frente a depurar juntas intermitentes que solo aparecen con cierto zoom.

Filtración de colores que aparece solo en una compilación publicada, no en el editor. Esto suele indicar que la compilación activa mipmaps o compresión de texturas que estaban desactivados en la vista previa. Prueba los atlas propensos a contaminación con los ajustes de la compilación final, no solo los predeterminados del editor.

¿Siguen importando las potencias de dos?

Históricamente, las GPU exigían dimensiones de textura potencia de dos (256, 512, 1024, 2048…) para gestionar eficientemente mipmaps y ciertos modos de repetición, y las texturas de otras dimensiones fallaban o recurrían a una ruta de renderizado más lenta. Las GPU y API modernas (OpenGL ES 3+, Metal, Vulkan, DirectX 11+) admiten nativamente texturas de dimensiones no potencia de dos sin una penalización significativa en renderizado 2D básico, así que ese requisito estricto ha desaparecido en gran medida en equipos actuales.

Sigue importando en situaciones concretas:

  • Mipmapping. Algunas plataformas y API antiguas siguen exigiendo dimensiones que sean potencias de dos para generar correctamente una cadena completa de mipmaps. Si tu atlas usa mipmaps, comprueba el requisito real de la plataforma de destino en vez de asumirlo.
  • Hardware antiguo o limitado. Los móviles básicos, los contextos WebGL 1 y algunos dispositivos integrados todavía se benefician de tamaños potencia de dos o los requieren.
  • Alineación de memoria y formatos de compresión. Los formatos de compresión por bloques, muy utilizados en móviles, comprimen en bloques de tamaño fijo y a veces amplían dimensiones no compatibles hasta el siguiente tamaño válido. Elegir de antemano una potencia de dos evita que ese margen silencioso consuma memoria innecesaria.

En equipos actuales de escritorio, consolas o móviles modernos con flujo 2D estándar, el atlas no necesita potencias de dos. Para WebGL 1, móviles antiguos o sistemas integrados sigue siendo lo más seguro y cuesta poco: al activar el ajuste, la mayoría redondea al siguiente tamaño potencia de dos.

Recorte y pivotes

Recorte significa recortar cada sprite a su contenido opaco antes de situarlo en el atlas, descartando margen transparente. Casi siempre mejora la densidad: un personaje pequeño con mucho relleno ocupa mucho menos recortado.

El recorte cambia tamaño y desplazamiento efectivos, importante si la lógica o animación exige dimensiones y pivote comunes respecto al lienzo original. Una pose inclinada a izquierda tiene límites opacos distintos de otra a derecha; recortadas aparte, quedan de tamaños diferentes y alternarlas directamente desplaza al personaje.

Todas las herramientas de atlas que admiten recorte también registran el tamaño y el desplazamiento originales sin recortar junto con los datos recortados para resolver esto: el motor vuelve a representar el sprite recortado en su posición correcta dentro del fotograma original, por lo que el pivote sigue siendo visualmente consistente aunque se use menos espacio de textura para almacenar píxeles transparentes. Sprite Atlas de Unity y el importador de Godot lo gestionan automáticamente siempre que el recorte se active mediante la herramienta, en lugar de hacerlo a mano antes de empaquetar; recortar manualmente los sprites antes de empaquetarlos elimina los metadatos de desplazamiento que el motor necesita para recolocarlos correctamente.

¿Un atlas o varios?

Meterlo todo en un único megaatlas no es automáticamente mejor. Algunas razones prácticas para dividir en varios atlas:

  • Residencia en memoria. Si un nivel solo utiliza una parte de tus sprites, cargar un atlas por nivel o escena evita mantener en memoria GPU datos de sprites que pertenecen a contenido del que el jugador no está cerca.
  • Límites de tamaño de textura. El hardware impone una dimensión máxima de textura, normalmente 4096 u 8192 en equipos modernos y menor en móviles antiguos. Un conjunto suficientemente grande de sprites no cabrá en un atlas, independientemente de la eficiencia del empaquetado.
  • Frecuencia de actualización. Los sprites que cambian a menudo, como una interfaz en rápida iteración, se benefician de tener su propio atlas separado del arte estable que apenas cambia. Así, un cambio pequeño no obliga a reconstruir y volver a subir todo el atlas.
  • Diferencias de material. Los sprites que necesitan distintos shaders o modos de mezcla no pueden agruparse en el mismo lote de renderizado, aunque compartan atlas; por eso combinarlos no aporta ventajas de empaquetado.

Una opción predeterminada razonable es agrupar por contexto de uso: un atlas para las piezas del entorno de un nivel, otro para sus personajes y otro para la interfaz. Combínalos más solo si las mediciones muestran que las llamadas de dibujo son realmente un cuello de botella en el equipo de destino.

Preguntas frecuentes

¿Cuánto margen necesito realmente?

Uno o dos píxeles bastan en la mayoría de los casos a escala nativa y sin mipmaps. Si amplías mucho en ejecución o activas mipmaps, aumenta el relleno. No existe una cifra universal: prueba tu atlas con las escalas y niveles de zoom reales del juego.

¿Por qué la filtración solo aparece con ciertos niveles de zoom?

Ese patrón indica contaminación de mipmaps, no del filtrado a resolución base: el nivel muestreado a esa distancia se generó mezclando a través del límite de un sprite. Extrusión y relleno adecuado resuelven ambas causas, pero si es específico de mipmaps, asegúrate de que el relleno sobreviva a varios niveles de reducción, no solo a la textura base.

¿Debo preocuparme por esto si no uso mipmaps ni escalo sprites?

Menos, pero no cero. Incluso con renderizado 1:1 perfecto y filtrado puntual, las posiciones subpíxel de cámara o posiciones no enteras de sprites pueden hacer que la GPU muestree un píxel fraccionario que cruza un límite. Un pequeño margen es una protección barata incluso en una configuración 2D de píxeles perfectamente alineados.

¿El recorte afecta a las cajas de impacto o formas de colisión?

No si las colisiones se definen por separado, lo habitual. Si tu proyecto las deriva automáticamente de las dimensiones del sprite, comprueba si usa el tamaño recortado o el original: el recortado puede reducir inesperadamente la zona de impacto en fotogramas con mucho margen transparente.

¿Creas sprites para empaquetarlos en un atlas?

El generador de sprites reúne imágenes en filas con el relleno elegido: el empaquetado por estantes descrito, no rectángulos máximos, suficiente para muchos iconos y fotogramas. Si aún están unidos, el divisor de hojas los separa primero. Ambos se ejecutan en el navegador sin subidas.

Abrir Generador de sprites