Sigue estas prácticas recomendadas para optimizar la apariencia y el rendimiento de las texturas en el juego de Android.
Las texturas son uno de los componentes centrales del arte 3D. Los juegos en 3D que se ejecutan bien en la mayoría de los dispositivos comienzan con arte 3D diseñado para aprovechar al máximo los procesadores de gráficos. En esta guía, se destacan optimizaciones y prácticas recomendadas para texturas en dispositivos móviles a fin de mejorar el rendimiento del juego y minimizar el consumo de energía, a la vez que mantienes una alta calidad visual.
Crea un atlas de texturas
Un atlas de texturas es una textura que se diseñó para contener los datos de imagen de varios objetos gráficos, como objetos 2D o mallas 3D. En lugar de que cada objeto tenga su propia textura, se usa un atlas de ellas para combinar las imágenes de cada objeto.
Es importante minimizar la cantidad de llamadas de dibujo de un fotograma de juego para lograr un rendimiento óptimo durante la renderización. Puedes usar la misma textura para diferentes objetos como un factor a fin de combinarlas en una sola llamada de dibujo. Es importante reducir las llamadas de dibujo, en especial para los juegos que se vinculan a la CPU, ya que cada llamada genera una sobrecarga de la CPU mientras el controlador gráfico la procesa. Los atlas de texturas también reducen la cantidad de archivos de elementos de textura en los datos de tiempo de ejecución del juego. Se pueden consolidar cientos o incluso miles de texturas en una cantidad mucho menor de archivos de atlas de texturas.
Cuando creas mallas 3D, debes planificar el diseño del atlas de texturas. Si se crea el atlas antes de crear el recurso de malla, este debe separarse con UV después del atlas de texturas. Si se crea el atlas después de crear el elemento de malla, mediante herramientas de creación de atlas o de combinación en el software de pintura, la isla UV deberá volver a organizarse según la textura.
Agrupa en lotes las llamadas de dibujo específicas del motor
El motor de juego de Unity tiene una función de agrupación en lotes de llamadas de dibujo que puede combinar objetos automáticamente. Para hacerlo, estos deben compartir un material en común, incluidas las texturas, y deben estar marcados como estáticos.
Unreal Engine 4 requiere una configuración manual para agrupar en lotes. Puedes combinar objetos en software 3D antes de importarlos a Unreal. Unreal también incluye la herramienta UE4 Actor Merging, que puede combinar mallas y crear archivos de atlas de texturas.
Genera mipmaps
Los mipmaps son versiones de una textura con menor resolución. Una colección de mipmaps para una textura determinada se denomina cadena de mipmap. En una cadena, cada nivel posterior de ellos tiene menor resolución que el nivel anterior. Los mipmaps se usan para implementar el nivel de detalle (del inglés LOD) de texturas durante la renderización. Cuando una textura con mipmap se vincula a una etapa de textura, el hardware gráfico utiliza el espacio de textura que ocupa un fragmento para elegir un nivel de la cadena de mipmap. Cuando se renderiza una escena en 3D, el objeto alejado de la cámara usará un mapa MIP con menor resolución que el que se encuentre más cerca de la cámara.
Una textura con mipmap consume más memoria comparada con una sin ellos. Los niveles adicionales de mipmap aumentan un 33% el consumo de memoria de una textura. Si se dibuja una textura a una distancia fija de la cámara, la generación de mipmap representa un uso innecesario de la memoria.
El uso correcto de mipmaps mejora el rendimiento de la GPU. La disponibilidad de los niveles de mipmap con menor resolución reduce el uso del ancho de banda de la memoria y mejora la residencia de texturas en caché.
La generación de mipmaps también puede mejorar la calidad visual mediante la reducción de superposición de texturas. La superposición de texturas se puede observar como un efecto parpadeante en áreas más alejadas de la cámara.
Detalles de mipmaps específicos del motor
Para usar mipmaps, Unreal Engine 4 requiere dimensiones de textura que sean múltiplos de dos (p. ej., 512 x 1024, 128 x 128). Si una o ambas de las dimensiones de textura no son múltiplos de dos, no se generarán las cadenas de mipmaps.
Para crear mipmaps, el motor de Unity escalará automáticamente las texturas con dimensiones que no sean potencia de dos. Asegúrate de que las dimensiones de los archivos de textura de origen sean múltiplos de dos para evitar este escalamiento.
Selecciona los modos correctos para el filtrado de texturas
El filtrado de texturas es una función de renderización de hardware que afecta la apariencia visual de un triángulo renderizado. El uso correcto del filtrado de texturas puede mejorar la calidad visual de una escena. Existen varios modos para el filtrado de texturas, cada uno con un balance diferente entre la mejora de renderización y el costo. El costo incluye el tiempo de procesamiento y el ancho de banda de memoria. Los tres modos más frecuentes para el filtrado de texturas disponibles son el modo (o punto) más cercano, el filtrado bilineal y el filtrado trilineal. El filtrado anisotrópico es un método adicional para texturas que se puede combinar con el filtrado bilineal o trilineal.
Modo más cercano
El modo más cercano es el método de filtrado de texturas más simple y menos costoso. Este modo realiza muestras de un solo téxel usando coordenadas especificadas en la textura de origen. Los triángulos renderizados con el modo más cercano tendrán un aspecto pixelado o en forma de bloques, en especial cuando se renderizan cerca de la cámara.
Filtrado bilineal
El filtrado bilineal realiza muestras de los cuatro téxeles que rodean las coordenadas especificadas en la textura de origen. Estos cuatro téxeles se promedian a fin de determinar el color de textura para el fragmento. El filtrado bilineal produce un gradiente más suave entre los píxeles, lo que evita la apariencia en forma de bloques del filtrado más cercano. Los triángulos renderizados que se encuentran más cerca la cámara se verán borrosos en lugar de pixelados. Esta clase de filtrado cuesta más que el más cercano debido a las muestras de téxel y el cálculo del promedio adicionales.
Filtrado trilineal
Cuando renderizas una malla en la que varía la distancia de los vértices de la cámara, se pueden seleccionar varios niveles de mipmaps durante la renderización. Los cambios entre dos niveles de mipmaps pueden generar un corte nítido y notable en el punto de transición. Para suavizar estas transiciones, el filtrado trilineal realiza uno bilineal en dos niveles de mipmaps diferentes y, luego, interpola los resultados. Debido al uso de varios niveles de mipmaps y la interpolación, el filtrado trilineal es más costoso en términos de procesamiento si se lo compara con el bilineal.
Filtrado anisotrópico
El filtrado anisotrópico aumenta la calidad visual de las mallas con texturas que se renderizan en un ángulo extremo en relación con la cámara. Un ejemplo frecuente de esta clase de malla son los planos del terreno. Para funcionar, el filtrado anisotrópico requiere texturas con mipmaps. Durante la renderización, se puede configurar la proporción o el nivel del filtrado anisotrópico que se aplica. El costo del filtrado anisotrópico aumenta a medida que lo hace el nivel.
Estrategia para seleccionar el modo
Por lo general, el filtrado bilineal es el mejor equilibrio entre el rendimiento y la calidad visual. El filtrado trilineal requiere un ancho de banda de la memoria significativamente mayor y debe usarse de manera selectiva. En muchos casos, el filtrado bilineal combinado con el filtrado anisotrópico de nivel 2 se verá mejor y tendrá un mejor rendimiento que el filtrado trilineal con filtrado anisotrópico de nivel 1. El aumento de los niveles anisotrópicos para que superen el nivel 2 es demasiado costoso, y debe hacerse de manera muy selectiva para elementos esenciales del juego.
El filtrado de texturas podría representar hasta la mitad del consumo total de energía de la GPU. Una excelente manera de reducir las demandas de energía del juego es elegir filtros de texturas más simples siempre que sea posible.
Optimiza los tamaños de las texturas
Asegúrate de que las dimensiones de las texturas sean lo más pequeñas posible teniendo en cuenta la calidad de la imagen que deseas. Revisa los elementos de textura para comprobar si, por error, se crearon texturas grandes. Este principio aplica a las texturas discretas y las de atlas. Si el juego admite muchos dispositivos que abarcan una gran variedad de capacidades de resolución y rendimiento, considera crear versiones con baja y alta resolución de los elementos de textura para la clase correcta de dispositivos.
Cuando renderices una malla que usa varias texturas en su material, considera reducir la resolución de algunas texturas de manera selectiva. Por ejemplo, cuando se usa una textura difusa de 1024 x 1024, es posible reducir la aspereza o la textura metálica del mapeo de textura a 512 x 512 con solo un impacto mínimo en la calidad de la imagen. Verifica el impacto de todos estos experimentos en el cambio de tamaño para asegurarte de que no afecten el nivel de calidad que deseas.
Usa el espacio de color correcto
Muchos paquetes de software que se usan para crear texturas operan en el espacio de color sRGB y exportan con este. Es posible que las texturas difusas, que se procesan como color, usen el espacio de color sRGB. Las texturas que no se procesan como color, como los mapas de texturas metálicas, de aspereza o normales, no se deben exportar al espacio de color sRGB.
La configuración de texturas de los motores de juego incluye un parámetro para determinar si una textura usa el espacio de color sRGB.
Como los datos de píxeles de estas texturas no se utilizan como datos de color, el uso del espacio de color sRGB producirá imágenes incorrectas.
Usa la compresión de texturas
La compresión de texturas es un algoritmo de compresión de imágenes que se aplica a datos de píxeles sin comprimir y que genera una textura que el hardware de gráficos puede descomprimir con rapidez durante la renderización. El uso efectivo de la compresión de texturas puede reducir el uso de memoria y aumentar el rendimiento con un impacto mínimo en la calidad visual. En Android, los tres algoritmos más frecuentes para la compresión de texturas son ETC1, ETC2 y ASTC. En el caso de los juegos modernos, ASTC suele ser la primera mejor opción, y ETC2 es una opción de resguardo por si el juego se orienta a dispositivos que no admiten ASTC.
ETC1
ETC1 es compatible con todos los dispositivos Android. ETC1 solo admite un único modo de cuatro bits por píxel de datos de color RGB. ETC1 no admite canales alfa. Muchos motores de juego que admiten ETC1 permiten designar una segunda textura ETC1 para que represente los datos de los canales alfa.
ETC2
ETC2 es compatible con más del 90% de los dispositivos Android activos. Los dispositivos muy antiguos que no son compatibles con la API de OpenGL ES 3.0 no pueden usar ETC2. En comparación con ETC1, ETC2 agrega lo siguiente:
- Compatibilidad con canales alfa, tanto "perforación" de ocho bits como de un bit
- Versiones sRGB de texturas RGB y RGBA
- Texturas de uno y dos canales, R11 y RG11
ASTC
ASTC es compatible con más del 75% de los dispositivos Android activos. ASTC tiene tamaños de bloques de compresión configurables, lo que brinda un control detallado y equilibra la proporción de compresión con la calidad de la imagen para una textura determinada. Con frecuencia, ASTC logra una calidad superior con el mismo tamaño de memoria que ETC2, o bien puede alcanzar una cantidad similar con una memoria más pequeña que ETC2.
Velocidad de la compresión de texturas
La compresión de texturas puede demorar mucho tiempo si el juego tiene demasiadas. Tanto en ETC como ASTC, se pueden seleccionar parámetros de configuración para la calidad de compresión. Los parámetros de mayor calidad requieren más tiempo para comprimir. Durante el desarrollo, te recomendamos que disminuyas el nivel de calidad para reducir el tiempo de compresión y aumentar el nivel de calidad antes de crear compilaciones importantes.
Compresión de texturas en motores de juego
Si usas un motor de juego, es posible que debas elegir el formato de compresión de texturas (ETC o ASTC) a nivel del proyecto. Para brindar la máxima compatibilidad, podría necesitarse trabajo adicional admitir varios formatos de compresión. La función de orientación de formato de compresión de texturas de Google Play Asset Delivery puede ayudarte a incluir varios formatos en el juego y entregar únicamente el formato más óptimo para un dispositivo individual en el momento de la instalación.
Extiende las islas UV
Mantén la isla UV lo más recta posible, ya que ayuda a la textura de las siguientes maneras:
- El empaquetado de las islas UV es más sencillo, lo que genera menos desperdicio de espacio.
- Las islas UV rectas reducen el "efecto escalera" en las texturas.
- El empaquetado correcto de las islas UV garantiza que la textura brinde una resolución óptima.
- Se obtienen texturas de mejor calidad, incluso si las islas UV están ligeramente distorsionadas por enderezarlas.
En un modelo, las uniones visibles de las texturas no lucen bien. Ubica las uniones UV en lugares en los que sean menos visibles. A fin de crear mapas normales de mejor calidad, divide la isla UV en donde los bordes sean nítidos y deja espacio alrededor de la isla.
Evita detalles imperceptibles
Cuando creas elementos artísticos, no agregues detalles que no se verán, en especial en los juegos diseñados para dispositivos con pantallas más pequeñas. Crear una textura de 4096 x 4096 con detalles complejos es un desperdicio para un modelo de silla pequeña que apenas se puede ver en la esquina de una habitación. En algunos casos, es posible que debas exagerar los bordes (agregar elementos destacados adicionales) y el sombreado para mejorar la percepción de la forma.
Integra los detalles
Los dispositivos móviles tienen pantallas más pequeñas y hardware gráficos con menor potencia si se los compara con las computadoras personales o las consolas de juegos. En lugar de calcular efectos, como la oclusión del ambiente o el destacado especular en el tiempo de ejecución, considera integrarlos en la textura difusa cuando sea posible, ya que ayuda al rendimiento y garantiza la visibilidad de los detalles.
Ajusta el tono de color
Si tienes la capacidad de crear sombreadores personalizados y cuentas con mallas que tienen un esquema de colores similar o uniforme, considera ajustar el tono de color en las mallas que correspondan. Con el ajuste del tono de color, se usa una textura en escala de grises, que requiere menos memoria de textura que una textura RGB. El sombreador aplica los datos de color por vértice para colorear la malla. Como método alternativo para ajustar el tono, puedes usar una máscara RGB y aplicar la textura según el rango de colores de la máscara.
Empaqueta los canales de texturas
Cuando renderices materiales con varias texturas, considera la posibilidad de combinar las texturas que solo usen un canal de color en una sola textura que utilice los tres canales de color. De esta manera, se reduce el uso de memoria y, además, se disminuye la cantidad de operaciones de muestras de texturas que realiza el sombreador de fragmentos.
Cuando realices el empaquetado, asigna los datos con más detalles al canal verde. Como el ojo humano es más sensible al verde, por lo general, el hardware de gráficos asigna más bits al canal de este color. Por ejemplo, con frecuencia, un mapa de aspereza y suavidad tendrá más detalles que un mapa de textura metálica y es una mejor opción para asignar al canal verde.
En el caso de los materiales que usan un canal alfa, si solo usas dos canales en la textura empaquetada, considera colocar los datos del canal alfa en la textura empaquetada en lugar de hacerlo en la textura difusa. Según el formato de la textura difusa, esto puede ayudarte a reducir su tamaño o aumentar la calidad visual si omites los datos del canal alfa.
Asegúrate de que las texturas empaquetadas estén configuradas en un espacio de color RGB lineal y no en uno sRGB.
Crea mapas normales
El mapeo normal es una técnica que le brinda a un modelo 3D la apariencia de los detalles sin usar geometría adicional. Las características, como arrugas o pernos que podrían requerir muchos triángulos para modelar, se pueden simular con un mapa normal. Es posible que el mapeo normal sea adecuado o no, según el estilo artístico y la dirección del juego.
Los mapas normales generan cierto costo de rendimiento y deberían usarse con moderación en dispositivos de gama baja. El mapa normal requiere una textura adicional, lo que produce una muestra de texturas y cálculos del sombreador de fragmentos adicionales.
Prácticas recomendadas para mapas normales
A continuación, se mencionan algunas prácticas recomendadas para crear mapas normales:
Usa un contenedor
Un contenedor es una versión más grande, o extendida, del modelo con pocos polígonos. Necesita incluir el modelo con gran cantidad de polígonos para que funcione bien durante la integración normal del mapa. El contenedor se usa para limitar la distancia de la proyección de rayos durante la integración normal del mapa y ayuda a evitar problemas con las uniones normales divididas en el mapa normal.
Realiza la integración por coincidencia con el nombre de la malla
Si el software de integración lo admite, realiza la integración por coincidencia con el nombre de la malla. Esta función mitiga el problema de proyectar, de manera incorrecta, un mapa normal. Cuando los objetos están demasiado cerca entre sí, pueden proyectar, de manera inesperada, su mapa normal en la superficie incorrecta. La coincidencia con el nombre de la malla garantiza que la integración solo se lleve a cabo en la superficie correcta. Para obtener más información sobre esta función de Substance Painter, consulta esta página. Para obtener más información sobre esta función en Marmoset Toolbag, consulta esta página.
Expande la malla
Considera expandir la malla si no puedes lograr que coincida con el nombre de la malla durante la integración. Si la expandes, se separarán las partes entre sí, de modo que el mapa normal no se proyectará en la superficie incorrecta. Si también realizas la integración para la oclusión del ambiente, es posible que debas llevar a cabo la integración por separado sin expandir la malla.
Minimiza las uniones
Las islas UV continuas en los bordes rígidos causarán uniones visibles; divide las UV en estos bordes para minimizar ese efecto. Cuando configuras grupos de suavizado, como regla general, mantén el ángulo inferior a 90 grados. Las uniones UV deben tener un grupo de suavizado diferente en los triángulos.