Por qué glTF ganó a OBJ, FBX y COLLADA
La distinción entre formato de intercambio y formato de entrega, qué problema concreto resolvía cada predecesor y por qué ninguno servía para la web.
Intercambio contra entrega
Un formato de intercambio existe para mover una escena entre dos programas de autoría sin perder información. Tiene que representar historiales de modificadores, curvas paramétricas, jerarquías de materiales con nodos arbitrarios, capas, metadatos del artista. Es rico, complejo y su prioridad es la fidelidad.
Un formato de entrega existe para llegar a un dispositivo y renderizarse. Su prioridad es la contraria: mínimo trabajo de decodificación, correspondencia directa con lo que la GPU necesita, y ninguna ambigüedad sobre cómo se ve el resultado.
Los dos objetivos se contradicen. Un formato que guarda un modificador de subdivisión obliga al consumidor a implementar la subdivisión; un formato que guarda el resultado de la subdivisión es directamente subible a un buffer. glTF eligió lo segundo, y esa es la decisión de diseño que lo define. Su propia especificación se describe como “an efficient, extensible, interoperable format for the transmission and loading of 3D content”: transmisión y carga, no autoría.
Qué falla en cada predecesor
OBJ, de Wavefront, 1980s. Texto plano, geometría y poco más. Sus defectos son estructurales y no se pueden parchear:
- No tiene jerarquía de escena. No hay nodos, no hay transformaciones, no hay padres e hijos. Un OBJ es una bolsa de triángulos.
- No tiene animación. Ninguna.
- Los materiales viven en un fichero
.mtlaparte, con un modelo de iluminación de Phong de los ochenta que no tiene nada que ver con PBR. - Es texto. Un vértice ocupa unos 30 bytes en ASCII contra 12 en binario, y hay que parsearlo con
parseFloat. Un modelo de un millón de triángulos en OBJ son 100 MB de texto y varios segundos de parseo en JavaScript.
FBX, de Kaydara y después Autodesk, 1996. Es el formato de intercambio dominante en la industria y es técnicamente capaz. Su problema no es técnico:
- Es propietario. La especificación no está publicada. La forma oficial de leerlo es el FBX SDK de Autodesk, que es C++, tiene licencia restrictiva y no existe para navegadores.
- Todos los lectores de FBX que no son de Autodesk son ingeniería inversa. El
FBXLoaderde Three.js lo es, y por eso tiene lagunas conocidas y falla con ficheros de ciertas versiones. - Su modelo de materiales es el de Maya y 3ds Max, no PBR estándar, así que la conversión siempre es aproximada.
COLLADA, del Khronos Group, 2004. El intento anterior de Khronos y el antecesor directo de glTF. Estándar abierto, bien documentado, y aun así fracasó:
- Es XML. Un
.daede un modelo mediano ocupa decenas de megabytes, y parsear XML en JavaScript es lento incluso con el parser nativo. - Es un formato de intercambio con todo lo que eso implica: soporta tantas formas de expresar lo mismo que dos exportadores producen ficheros incompatibles en la práctica. La especificación es tan permisiva que la conformidad no garantiza la interoperabilidad.
- No tiene modelo de materiales PBR, porque en 2004 no existía el consenso.
Khronos escribió glTF sabiendo exactamente esto, porque el fracaso de COLLADA era suyo. La lección que sacaron y que aparece en el diseño de glTF es: menos formas de expresar cada cosa, y ninguna que requiera cómputo del consumidor.
Qué significa runtime-ready
La propiedad que define a glTF es que sus datos ya están en el formato que la GPU consume. Concretamente:
La geometría son buffers binarios. Los vértices están en arrays tipados, con el mismo layout que espera gl.bufferData. No hay que parsear, ni convertir, ni reordenar: se lee un trozo de ArrayBuffer y se sube.
Los triángulos ya están trianguladados. No hay n-gons, no hay quads, no hay superficies paramétricas. Todo lo que llega es triángulos, líneas o puntos: exactamente los modos primitivos de OpenGL.
Los materiales son PBR metallic-roughness estándar. Un modelo que se ve de una manera en Blender se ve igual en Three.js, en Babylon, en el visor de Windows y en Sketchfab, porque el modelo de iluminación está especificado y es el mismo.
Las transformaciones son matrices o TRS. Traslación, rotación en cuaternión y escala. Nada de historiales ni de restricciones.
La consecuencia para el cargador es medible: GLTFLoader puede pasar de bytes a una escena renderizable con muy poco trabajo de CPU, y la parte más costosa —descomprimir geometría o transcodificar texturas— se puede delegar a workers. Un OBJ o un DAE del mismo modelo bloquean el hilo principal durante segundos parseando texto.
Lo que glTF sí trajo de nuevo
Además de corregir los defectos de los otros, glTF aportó dos cosas que ninguno tenía.
Un modelo de extensiones versionado y con gobernanza. Las extensiones se registran, se documentan y llevan prefijo según su estatus: KHR_ para las ratificadas por Khronos, EXT_ para las de múltiples vendedores, y prefijos de vendedor para el resto. Un fichero declara en extensionsUsed cuáles emplea y en extensionsRequired cuáles son imprescindibles, de forma que un cargador puede rechazar limpiamente lo que no entiende en lugar de renderizar algo incorrecto.
Compresión pensada para la web desde el principio. KHR_draco_mesh_compression, KHR_texture_basisu y EXT_meshopt_compression no son parches: son extensiones de primera clase con soporte en todos los cargadores serios. Ningún formato anterior tenía una historia de compresión que funcionase en un navegador.