Skip to content

Cómo optimizar archivos GLB para la web: Draco, Meshopt y KTX2 (2026) ​

Última actualización: septiembre de 2026.

Un gran cofre del tesoro pasa por un tubo y se convierte en una copia diminuta de sí mismo

Para optimizar un GLB para la web, sigue este orden: reduce primero las texturas (limítalas a 1024 o 2048 y vuelve a codificarlas como WebP para reducir el tamaño de descarga o como KTX2 para reducir la memoria de la GPU), cuantiza los datos de los vértices, comprime la geometría con Meshopt (o con Draco cuando ahorrar los últimos cientos de kilobytes importe más que el tiempo de decodificación), simplifica la malla si el número de triángulos sigue siendo absurdo y, después, elimina lo innecesario, deduplica y une lo que quede. Un solo comando hace casi todo: gltf-transform optimize in.glb out.glb --texture-compress webp. El orden importa porque las texturas suelen representar el 80 por ciento o más del archivo y toda la memoria de vídeo.

Respuesta rápida ​

  • Modelo con muchas texturas (la mayoría): redimensiona a 1024 o 2048 y ejecuta después gltf-transform webp. Si da tirones o se bloquea en teléfonos, conviértelo a KTX2, ya sea en el navegador con el compresor KTX2 o con gltf-transform etc1s/uastc.
  • Modelo con mucha geometría (escaneos, CAD, generado por IA): ejecuta gltf-transform simplify y después meshopt. Draco comprime un poco más, pero se decodifica más despacio y necesita un decodificador diez veces mayor.
  • Personaje animado: Meshopt, no Draco. Draco no modifica las pistas de animación ni los morph targets.
  • El archivo debe abrirse en un motor que no controlas: ejecuta gltf-transform quantize. No requiere decodificador, solo KHR_mesh_quantization, que pueden leer todos los cargadores indicados aquí.
  • Sin terminal: el optimizador de GLB ejecuta en tu navegador la eliminación de elementos innecesarios, la soldadura, la unión, la simplificación, el redimensionamiento de texturas a WebP y Meshopt, mostrando el tamaño en cada paso.

Referencia rápida ​

Solo cuantizaciónMeshoptDraco
ExtensiónKHR_mesh_quantizationEXT_meshopt_compression (+ cuantización)KHR_draco_mesh_compression
Qué comprimeAtributos de vértices (menos bits)Vértices, índices, morph targets y animaciónSolo geometría de mallas triangulares
Tamaño de nuestro modelo de prueba de 28 MB22,8 MB (8,1 MB con gzip)5,1 MB (3,3 MB con gzip)2,6 MB (2,5 MB con gzip)
DecodificadorNingunoMódulo JS de 32 KB con WASM integradoDe 192 a 286 KB de WASM más un wrapper de 58 KB y una alternativa en JS de 719 KB
Velocidad de decodificaciónInstantánea; la GPU lo lee directamenteAproximadamente 1 GB/s con SIMD de WASM, según la especificaciónBastante más lenta que Meshopt, según la documentación de glTF-Transform
Necesita gzip/brotli en el servidorAyuda muchoSí, está diseñado para elloAporta poca mejora
Cargadoresthree.js, Babylon.js, PlayCanvas, glTFastthree.js r122+, Babylon.js 5.0+, glTFast (paquete adicional), no PlayCanvasthree.js, Babylon.js, PlayCanvas, glTFast (paquete adicional)

Los mismos datos en forma de barras, junto con los resultados de gltfpack y de la simplificación obtenidos en la comparativa.

Un modelo, todos los códecsSalida de TRELLIS.2 de 28,7 MB, 978.226 triángulos. gltf-transform 4.5.0 y gltfpack 1.2.archivo sin comprimircon gzipOriginalgeometría float32, texturas de 1,1 MB28,7 MBquantizeKHR_mesh_quantization, sin decodificador22,8 MB8,1 MBmeshopt --level highEXT_meshopt_compression5,1 MB3,3 MBgltfpack -ccMeshopt, modo de mayor compresión4,4 MB3,1 MBdracoKHR_draco_mesh_compression2,6 MB2,5 MBsimplify --ratio 0.25244.556 triángulos8,1 MBantes de comprimir, por lo que aún puede aplicarse cualquiera de los códecs anterioresLos valores predeterminados de optimize (ratio 0, error 0.0001) redujeron el mismo archivo a 6.582 triángulos.
Draco gana en número de bytes, pero gzip apenas aporta nada, mientras que Meshopt y la salida cuantizada dependen de la compresión del servidor. La simplificación es el único paso que cambia el número de triángulos, por lo que sus 8,1 MB son un nuevo punto de partida, no la meta.

En qué se emplean los bytes de un GLB ​

Ejecuta gltf-transform inspect model.glb antes que nada. Enumera cada malla con su número de vértices y tipos de atributos, cada textura con su tamaño codificado y su gpuSize, y cada animación con su número de fotogramas clave. Las cifras de esta guía proceden de la documentación de las herramientas y de las especificaciones de las extensiones, además de una comparativa que realizamos esta semana con gltf-transform 4.5.0 y gltfpack 1.2 sobre dos archivos reales. Los resultados muestran los dos tipos de archivos que encontrarás.

Un objeto de Sketchfab de 2,2 MB (una taza low-poly) tenía 680 triángulos y 39 KB de geometría. Los otros 2,18 MB correspondían a tres PNG de 1024×1024, por lo que las texturas representaban el 98 por ciento del archivo, e inspect estimaba 5,59 MB de VRAM para cada una una vez generados los mipmaps. Es el caso habitual de los recursos creados a mano.

Una salida de TRELLIS.2 de 28,7 MB era justo lo contrario: 978.226 triángulos y 27,5 MB de geometría float32, con solo 1,1 MB de texturas. Sin embargo, esas dos texturas eran de 4096×4096, lo que, según inspect, supone 89,5 MB de VRAM por textura. Los modelos del generador de modelos 3D y de otras herramientas similares suelen llegar así, con demasiada densidad y texturas excesivas, por lo que necesitan tanto los pasos de geometría como los de texturas.

En qué se emplean los bytesTamaño codificado por contenido. La memoria de la GPU es una cifra aparte, a la derecha.texturasgeometríatodo lo demás (animación, JSON, esqueletos)Recurso típico creado a manotexturas, 80 por ciento o mástodo lo demásreparto típicoTaza de Sketchfab de 2,2 MB, 680 triángulostres PNG de 1024x1024, 2,18 MB (98 por ciento)geometría, 39 KB5,59 MB de VRAMpor textura, con mipmapsSalida de TRELLIS.2 de 28,7 MB, 978.226 triángulosgeometría float32, 27,5 MBtexturas, 1,1 MB, dos de 4096x409689,5 MB de VRAMpor textura, con mipmaps
La fila «típica» es la regla general; las otras dos corresponden a los archivos reales de la comparativa. Observa la columna de la derecha: las texturas de 1024 de la taza y las de 4096 de TRELLIS.2 ocupan poco en disco, pero tienen requisitos de memoria de vídeo radicalmente distintos.

Ten en cuenta que el tamaño codificado de una textura y su tamaño en la GPU no guardan relación. Un PNG de 4 MB y un WebP de 200 KB de la misma imagen de 2048×2048 ocupan ambos unos 22 MB en la memoria de vídeo entre los píxeles sin comprimir y los mipmaps. Solo KTX2 cambia esa cifra.

Los seis pasos siguientes se ejecutan en este orden porque cada uno reduce lo que el siguiente debe procesar.

El orden de triajePrimero, la mayor mejora. Los tamaños corresponden al modelo de prueba de 28,7 MB.1Texturas: limitar a 1024 o 2048, después WebP o KTX2Suelen representar el 80 % o más del archivo y toda la memoria de vídeo2CuantizarDe 28,7 MB a 22,8 MB (8,1 MB con gzip), sin decodificador, compatible con cualquier cargador3Meshopt o Draco5,1 MB (3,3 con gzip) o 2,6 MB (2,5 con gzip), decodificador en el cliente4SimplificarDe 978.226 triángulos a 244.556 con una proporción de 0,25, idéntico a distancia de juego5Eliminar, deduplicar, unir e instanciarMejoras gratuitas: elimina lo que no tiene referencias y reduce 200 llamadas de dibujo a unas pocas6Animación: remuestrearElimina fotogramas clave situados en la línea entre sus vecinos, sin pérdidas en la práctica
Sigue los números de arriba abajo. Los pasos 1 y 4 son donde se concentra la mayoría de los bytes, el paso 2 es imperceptible salvo en una única malla gigantesca y el paso 5 debe ejecutarse con cuidado en un personaje con esqueleto, ya que la unión fusiona piezas que deberían moverse.

Paso 1: texturas ​

Dos problemas distintos, dos soluciones distintas.

El tamaño de descarga se corrige redimensionando y recodificando. Pocos objetos necesitan más de 1024×1024, y un personaje protagonista rara vez necesita más de 2048. gltf-transform resize --width 1024 --height 1024 limita las dimensiones sin aumentarlas nunca, y gltf-transform webp recodifica con sharp. En la taza, solo WebP redujo el archivo de 2,23 MB a 246 KB. Redimensionarlo primero a 512 lo redujo a 96 KB sin cambios visibles en un objeto de ese tamaño. WebP requiere EXT_texture_webp, que los motores web pueden leer, pero glTFast de Unity no (su tabla de funcionalidades indica que «no se admitirá»).

La memoria de la GPU y el tiempo de carga solo se reducen con KTX2 y la supercompresión Basis Universal, que mantiene la textura en un formato de bloques de GPU hasta llegar a la VRAM y consume entre 4 y 8 veces menos memoria que RGBA sin comprimir. Tiene su propia sección más adelante porque los ajustes son importantes.

Una advertencia extraída de la comparativa: gltf-transform optimize utiliza --texture-compress auto de forma predeterminada, lo que recodifica las texturas en su formato original. En la taza, esto hizo que los PNG fueran más grandes y que el archivo pasara de 2,2 MB a 2,8 MB. Especifica webp o ktx2 explícitamente.

Paso 2: cuantizar ​

La cuantización almacena cada atributo de vértice usando menos bits. Una posición pasa de tres números de coma flotante de 32 bits a tres enteros de 16 bits, con la escala y el desplazamiento incorporados en la transformación del nodo (o en inverseBindMatrices para mallas con skinning). La especificación KHR_mesh_quantization sitúa un vértice típico en unos 20 bytes en lugar de 48. Es una extensión ratificada por Khronos que no requiere decodificador: la GPU lee directamente los atributos enteros, por lo que los archivos cuantizados ocupan menos tanto en la VRAM como durante la transferencia.

Los valores predeterminados de glTF-Transform son 14 bits para posiciones, 10 para normales y tangentes, 12 para UV y 8 para colores y pesos. Los de gltfpack son 14, 8, 12 y 8. Ambos son imperceptibles salvo en una única malla gigantesca, donde 14 bits aplicados a toda la extensión pueden provocar facetado visible. Por sí sola, la mejora de la cuantización es modesta: nuestro modelo de 28 MB bajó a 22,8 MB sin comprimir y a 8,1 MB con gzip. Su verdadera función es ser la primera mitad de Meshopt y ofrecer una salida segura cuando no se conoce bien el cargador de destino. Draco cuantiza internamente con los mismos valores predeterminados, por lo que no debes ejecutar quantize antes de draco.

Paso 3: Meshopt o Draco ​

Ambos son códecs de geometría con pérdidas que decodifican a búferes normales antes de cargarlos en la GPU, por lo que ninguno hace que el modelo se renderice más rápido. Reducen la descarga. Se diferencian en qué comprimen, a qué velocidad decodifican y cuánto pesa el decodificador que debes distribuir.

Meshopt (EXT_meshopt_compression) funciona en el nivel de bufferView, por lo que comprime los atributos de vértice, los índices, los deltas de morph targets y los fotogramas clave de animación. Está diseñado para aplicarse después de la cuantización y antes de gzip o brotli: el códec regulariza los bytes y el compresor de propósito general de la CDN hace el resto. La especificación indica velocidades de decodificación de unos 1 GB/s con SIMD de WebAssembly, y el decodificador de three.js es un único módulo de 32 KB. En el modelo de prueba: 5,1 MB sin comprimir y 3,3 MB con gzip, usando el valor predeterminado --level high.

Draco (KHR_draco_mesh_compression) solo comprime primitivas de malla triangular. Las animaciones, los morph targets, los puntos y las líneas se conservan sin cambios. Comprime más, hasta 2,6 MB en el mismo modelo, y gzip apenas ayuda porque el resultado ya es denso. El coste está en el tiempo de decodificación y el peso del decodificador: la documentación de glTF-Transform indica claramente que la decodificación de Meshopt es considerablemente más rápida, y el decodificador WASM incluido con three.js pesa 286 KB (192 KB en la compilación de la rama glTF), además de un wrapper de 58 KB y una alternativa en JavaScript de 719 KB. Draco también reordena los vértices y puede cambiar su cantidad.

En resumen: Meshopt para cualquier elemento animado, cualquier modelo con morph targets, cualquier caso en el que el tiempo de carga en un teléfono sea prioritario y cualquier contenido servido con brotli activado. Draco cuando el recurso sea una malla estática, predomine la geometría y ahorrar entre un 20 y un 30 % durante la transferencia compense un primer fotograma más lento. ¿No lo tienes claro? Meshopt. La opción -cc de gltfpack (Meshopt en su modo más potente) produjo 4,4 MB sin comprimir y 3,1 MB con gzip en el mismo archivo.

Paso 4: simplificar ​

Si el modelo sigue siendo grande después de comprimirlo, tiene demasiados triángulos, y ningún códec puede corregir eso. Ambas herramientas utilizan el simplificador de meshoptimizer, que acepta una proporción objetivo y un límite de error, y se detiene cuando alcanza cualquiera de los dos.

gltf-transform simplify --ratio 0.25 --error 0.01 intenta conservar el 25 % de los vértices con una desviación máxima equivalente al 1 % del radio de la malla. En el modelo de 978.000 triángulos produjo 244.556 triángulos y 8,1 MB antes de la compresión, con un aspecto idéntico a distancia de juego. Los valores predeterminados de optimize son más agresivos de lo que cabría esperar: --simplify-ratio 0 con --simplify-error 0.0001, lo que significa «eliminar todo lo posible con un error máximo del 0,01 %». En el mismo modelo con teselación excesiva, esto lo redujo a 6.582 triángulos, porque el generador había gastado casi un millón de triángulos en superficies planas. Suelda antes de simplificar (optimize lo hace), porque los vértices separados detienen el simplificador en las costuras.

La opción -si 0.25 de gltfpack aplica la misma idea, con -se 0.01 como límite de error predeterminado, -sa para alcanzar la proporción independientemente de la calidad y -slb para bloquear los vértices de los bordes y evitar que las mallas modulares abran huecos. Los objetos de superficies duras toleran fácilmente una reducción del 50 %, las mallas escaneadas y generadas por IA suelen tolerar la eliminación del 90 %, y los personajes con esqueleto requieren cuidado cerca de las articulaciones porque colapsar vértices también colapsa los pesos de skinning.

Paso 5: eliminar, deduplicar, unir e instanciar ​

Estas son mejoras gratuitas y optimize las ejecuta todas. prune elimina materiales, texturas, accesores y nodos a los que nada hace referencia, y convierte las texturas de un solo color en factores del material. dedup combina accesores y texturas idénticos que un exportador haya escrito dos veces. flatten aplana la jerarquía y join combina las mallas que comparten un material, lo que reduce 200 llamadas de dibujo a unas pocas. instance (a partir de 5 copias) convierte las mallas repetidas en EXT_mesh_gpu_instancing, y palette combina materiales que solo se diferencian por el color.

No utilices join ni flatten en un personaje con esqueleto ni en elementos cuyas partes se muevan por separado en el juego, porque esas partes desaparecen dentro de una sola malla. La solución de gltfpack es -kn (conservar nodos con nombre) y -km (conservar materiales con nombre).

Paso 6: animación ​

Los exportadores suelen crear un fotograma clave en cada fotograma. gltf-transform resample elimina los fotogramas clave situados en la línea entre sus vecinos (con una tolerancia predeterminada de 1e-4), lo que en la práctica no produce pérdidas. La opción -af 30 de gltfpack remuestrea cada pista a 30 Hz y cuantiza las traslaciones a 16 bits, las rotaciones a 12 y la escala a 16 (-at, -ar, -as) antes de que Meshopt las comprima. En un personaje típico con unos pocos clips, este paso aporta poco. En una biblioteca de movimientos puede ahorrar la mayoría de los bytes.

Las líneas de comandos ​

La CLI de glTF-Transform se instala con npm install --global @gltf-transform/cli o se ejecuta mediante npx @gltf-transform/cli. Todo de una vez:

bash
gltf-transform optimize in.glb out.glb --texture-compress webp --texture-size 1024

Esto ejecuta, en orden, deduplicación, instanciación, creación de paletas, aplanado, unión, soldado, simplificación (proporción 0, error 0,0001), remuestreo, eliminación, representación dispersa, compresión de texturas con un límite de 1024 y Meshopt con el nivel high. Añade --compress draco para usar Draco, --compress quantize para aplicar solo cuantización, --no-join --no-flatten para modelos con esqueleto o articulados, --simplify false si la silueta importa más que los bytes y --texture-compress ktx2 si KTX-Software está instalado.

Los pasos individuales, cuando quieras tener más control:

bash
gltf-transform inspect in.glb
gltf-transform resize in.glb a.glb --width 1024 --height 1024
gltf-transform webp a.glb b.glb --quality 80
gltf-transform weld b.glb c.glb
gltf-transform simplify c.glb d.glb --ratio 0.5 --error 0.001
gltf-transform meshopt d.glb out.glb --level high

Sustituye la última línea por gltf-transform draco d.glb out.glb (--encode-speed y --decode-speed aceptan valores del 0 al 10, con 5 de forma predeterminada; un valor menor produce un archivo más pequeño) o por gltf-transform quantize d.glb out.glb.

gltfpack se instala con npm install -g gltfpack o mediante un binario nativo de las versiones publicadas de meshoptimizer, que el README recomienda para archivos grandes. Sus valores predeterminados ya cuantizan, optimizan el orden de los vértices para la caché de la GPU y combinan mallas:

bash
gltfpack -i in.glb -o out.glb -cc -si 0.5 -tw -tl 1024 -kn

-cc usa Meshopt en el modo de mayor compresión (-c es el modo rápido y -cf añade una alternativa sin comprimir para los cargadores que no tengan el decodificador). -si 0.5 reduce los triángulos a la mitad dentro del límite -se 0.01. -tw convierte las texturas a WebP y -tl 1024 limita su tamaño. -kn conserva los nodos con nombre. Para KTX2, sustituye -tw por -tc (ETC1S) o -tc -tu (UASTC), lo que requiere una compilación de gltfpack vinculada con Basis Universal.

Si ninguna de las CLI es una opción, la herramienta para navegador ejecuta la misma secuencia.

Página del optimizador de GLB que muestra cómo un personaje de muestra de 4,0 MB se reduce a 676 KB, con el tamaño después de cada paso
La vía sin terminal: eliminación, soldado, unión, simplificación, redimensionado de texturas a WebP y Meshopt en el navegador, con una lectura del tamaño después de cada paso para que puedas ver cuál ha hecho el trabajo.

KTX2: ETC1S o UASTC ​

KTX2 es el contenedor de Khronos para texturas de GPU. Con la supercompresión Basis Universal, la textura se transcodifica durante la carga al formato de bloques disponible en el dispositivo (BC en equipos de escritorio, ASTC o ETC2 en móviles) y permanece comprimida en memoria. La extensión de glTF es KHR_texture_basisu. Basis tiene dos modos. ETC1S es el ligero: el README de Basis lo sitúa aproximadamente entre 0,3 y 3 bits por píxel en disco, con un control de calidad similar al de JPEG (de 1 a 255, 128 de forma predeterminada), y en memoria ocupa 4 bits por píxel en formatos como BC1 y ETC1. Úsalo para el color base de los elementos de atrezo. UASTC es el modo de calidad: 8 bits por píxel en memoria, un subconjunto de 19 modos de ASTC 4×4 y niveles de calidad de 0 a 4 (2 de forma predeterminada, que la ayuda de glTF-Transform sitúa en 47,47 dB). Los archivos UASTC son grandes en disco, así que combínalos con Zstandard: el valor predeterminado de uastc en glTF-Transform es --zstd 18, y ktx create --zstd admite valores de 1 a 22.

El cálculo para una textura de 2048×2048 con mipmaps: unos 22 MB como RGBA8, unos 5,6 MB como UASTC y unos 2,8 MB como ETC1S transcodificado a un formato de 4 bpp.

Hay tres reglas importantes. Los mapas de normales y de datos necesitan UASTC y espacio lineal. glTF-Transform advierte de que los mapas de normales RGB y los mapas de oclusión/rugosidad/metalidad pueden verse mal con ETC1S, y la especificación exige que las texturas de color estén marcadas como sRGB y los datos que no son de color como lineales. glTF-Transform lo configura por ti según la ranura. En el compresor KTX2, corresponde al selector sRGB: activado para el color y desactivado para los mapas de normales y datos. Las dimensiones deben ser múltiplos de 4 y se recomiendan potencias de dos. Genera mipmaps. La especificación indica que un KTX2 usado con minimización mediante mipmaps debe incluir la pirámide completa; de lo contrario, el motor tiene que descomprimirlos y generarlos en tiempo de ejecución. Los mipmaps están activados de forma predeterminada en glTF-Transform y en la herramienta del navegador, y se habilitan con --generate-mipmap en ktx create.

Los comandos de glTF-Transform necesitan el binario ktx de KTX-Software, versión 4.4.0 o posterior:

bash
gltf-transform uastc in.glb a.glb --level 2 --zstd 18 --slots "{normalTexture,occlusionTexture,metallicRoughnessTexture}"
gltf-transform etc1s a.glb out.glb --quality 128

Primero UASTC en las ranuras de datos y después ETC1S en el resto. Esa división —ETC1S para el color base y la emisión, y UASTC para las normales y ORM— es la habitual.

Cargar el resultado ​

Todos los códecs, excepto la cuantización, necesitan un decodificador en el cliente.

three.js. GLTFLoader lee KHR_mesh_quantization y EXT_texture_webp sin ninguna configuración. Para los demás, debes conectar los decodificadores, que se incluyen en el paquete three dentro de examples/jsm/libs/ como draco/, basis/ y meshopt_decoder.module.js. Copia draco/ y basis/ a una ruta pública y después:

js
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js'
import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js'
import { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js'

const draco = new DRACOLoader().setDecoderPath('/libs/draco/')
const ktx2 = new KTX2Loader().setTranscoderPath('/libs/basis/').detectSupport(renderer)
const loader = new GLTFLoader()
  .setDRACOLoader(draco)
  .setKTX2Loader(ktx2)
  .setMeshoptDecoder(MeshoptDecoder)

DRACOLoader elige el decodificador WASM cuando el navegador lo admite y recurre a JS cuando no. detectSupport(renderer) permite que KTX2Loader elija el formato de transcodificación adecuado para la GPU del dispositivo.

Babylon.js. El cargador de glTF admite Draco, Meshopt (desde la versión 5.0, sin configuración) y KTX2 descargando los decodificadores desde https://cdn.babylonjs.com y ejecutándolos en web workers. Para alojarlos por tu cuenta, configura Tools.CDNBaseUrl o especifica las configuraciones individuales: DracoDecoder.DefaultConfiguration (wasmUrl, wasmBinaryUrl, fallbackUrl), MeshoptCompression.Configuration.decoder.url y KhronosTextureContainer2.URLConfig para el conjunto de transcodificadores KTX2. Con npm, @babylonjs/ktx2decoder incluye los transcodificadores.

PlayCanvas. Draco se configura con dracoInitialize({ jsUrl, wasmUrl, numWorkers, lazyInit }), y el Editor puede aplicar compresión Draco durante la importación. KTX2 se gestiona mediante basisInitialize({ glueUrl, wasmUrl, fallbackUrl }). EXT_meshopt_compression no forma parte del analizador de GLB en la versión 2.x del motor (la solicitud de esta función de 2020 sigue abierta), así que para PlayCanvas elige Draco o una salida solo con cuantización.

Unity. El importador oficial es glTFast (com.unity.cloud.gltfast). KHR_mesh_quantization funciona sin configuración adicional, Draco necesita com.unity.cloud.draco, KTX2 necesita com.unity.cloud.ktx y Meshopt necesita com.unity.meshopt.decompress. WebP no es compatible por diseño, así que para un destino Unity usa KTX2.

Objetivos para un juego web móvil ​

No hay una especificación para esto, pero sí cifras que suelen funcionar bien en teléfonos. Mantén toda la primera escena por debajo de unos 10 MB transferidos por la red y carga el resto de forma progresiva (el tutorial de carga progresiva de recursos explica los niveles y el código). Mantén la VRAM de las texturas por debajo de 150 a 200 MB, lo que equivale a cuatro o cinco texturas de 2048 como RGBA8 o treinta como ETC1S. Mantén los elementos de atrezo por debajo de 5000 triángulos, un personaje protagonista por debajo de 30 000 a 50 000 y las llamadas de dibujo en unos pocos cientos. Usa texturas de 1024 para el atrezo y reserva las de 2048 para aquello a lo que se acerque la cámara. Sirve los GLB con Brotli o gzip activado, porque Meshopt y las salidas cuantizadas dependen de ello.

Verifica antes de publicar ​

El tamaño del archivo es la cifra sencilla. Abre el resultado en el visor de GLB y consulta el resto: el panel Extensiones confirma que EXT_meshopt_compression, KHR_draco_mesh_compression o KHR_texture_basisu se han incluido realmente en el archivo; la pestaña Texturas enumera cada textura de mayor a menor según su coste real de VRAM; y la barra de estado muestra en tiempo real las llamadas de dibujo y el número de triángulos. Después, comprueba las siluetas y las costuras UV en busca de artefactos de simplificación desde la distancia a la que las verá el jugador, y reproduce las animaciones para asegurarte de que la unión no haya fusionado una pieza que deba moverse. Si el archivo de origen no era un GLB, pasa primero el FBX u OBJ por el conversor de FBX a GLB, para comprimir el archivo que realmente cargarás.

Página del visor de GLB con un personaje de rana y un panel general de triángulos, llamadas de dibujo, huesos y tamaño de la geometría
Abre aquí la salida comprimida para confirmar que la extensión se ha incluido realmente en el archivo; después, consulta las llamadas de dibujo y el número de triángulos en la barra de estado, y el coste real de VRAM de cada textura en la pestaña Texturas.

Preguntas frecuentes ​

¿Cómo reduzco el tamaño de un archivo GLB? ​

Ejecuta gltf-transform inspect para comprobar si predominan las texturas o la geometría. Si son las texturas, redimensiónalas a 1024 o 2048 y conviértelas a WebP o KTX2. Si es la geometría, simplifícala y después comprímela con Meshopt o Draco. gltf-transform optimize in.glb out.glb --texture-compress webp realiza toda la secuencia, y el optimizador de GLB del navegador lo hace sin necesidad de instalar nada.

Draco frente a Meshopt: ¿cuál es mejor? ​

Meshopt para la mayoría de los juegos web. Decodifica mucho más rápido, incluye un decodificador de 32 KB en lugar de varios cientos de kilobytes de WASM y comprime animaciones y objetivos de morphing, que Draco omite. Draco produce archivos más pequeños para mallas estáticas (2,6 MB frente a 3,3 MB comprimidos con gzip en nuestro modelo de prueba de 28 MB) y es el que admite PlayCanvas, así que resulta mejor cuando el recurso es un escaneo estático y la geometría representa la mayor parte del archivo.

¿Qué es KTX2 y en qué se diferencia de Basis? ​

Basis Universal es el códec de compresión, con dos modos: ETC1S y UASTC. KTX2 es el archivo contenedor de Khronos que almacena datos de textura comprimidos con Basis, además de mipmaps y metadatos, y es lo que glTF referencia mediante KHR_texture_basisu. Las cadenas de producción más antiguas usaban un archivo .basis independiente. Usa .ktx2.

¿Debo usar ETC1S o UASTC? ​

ETC1S para el color base y todo aquello que no se vea de cerca: archivos pequeños y 4 bits por píxel en VRAM. UASTC para mapas de normales, rugosidad/metalidad/oclusión y texturas destacadas, con supercompresión Zstandard activada para que la descarga mantenga un tamaño razonable. Marca las texturas de color como sRGB y las texturas de datos como lineales, o las normales producirán un sombreado incorrecto.

¿Cómo comprimo texturas glTF? ​

Para reducir el tamaño de descarga, usa gltf-transform resize y después gltf-transform webp. Para reducir la memoria de la GPU, usa gltf-transform etc1s o uastc con KTX-Software instalado, o suelta los PNG en el compresor KTX2. En ambos casos, limita primero las dimensiones: una textura de 4096 ocupa 89 MB de VRAM como RGBA8 y casi nunca hay motivos para distribuir una en un navegador.

¿Por qué mi GLB es demasiado grande para three.js en dispositivos móviles? ​

Normalmente el problema no es el tamaño del archivo, sino la memoria de las texturas. Cuatro texturas RGBA de 2048 ocupan unos 90 MB de VRAM antes de que la escena haya dibujado nada, y los navegadores móviles cierran la pestaña al superar unos pocos cientos de megabytes. Convierte las texturas a KTX2 para que permanezcan comprimidas en la GPU, limítalas a 1024 siempre que puedas y llama a KTX2Loader.detectSupport(renderer) para que se transcodifiquen al formato del dispositivo.

¿gltfpack hace lo mismo que gltf-transform? ​

En su mayor parte, sí. gltfpack es un único binario nativo del proyecto meshoptimizer que, de forma predeterminada, cuantiza, reordena los vértices para la caché de la GPU, combina mallas y comprime con Meshopt. glTF-Transform es una biblioteca y CLI de Node que ofrece las mismas operaciones como pasos independientes y automatizables mediante scripts, además de generar salidas Draco, algo que gltfpack no hace. En nuestro archivo de prueba, sus salidas Meshopt quedaron con una diferencia de aproximadamente un 10 %.

Contenido relacionado ​