Converting 3D Models to GLB/GLTF Format for Android AR
GLB—binary glTF 2.0 container, Khronos Group standard. ARCore, Sceneform, model-viewer, WebXR—all use glTF/GLB. Unlike USDZ, GLB works cross-platform: Android AR, WebAR, Three.js, Babylon.js, Unity, Unreal.
But "open standard" doesn't mean "everything converts without issues."
GLB Structure and AR Requirements
glTF 2.0 describes scene via JSON: meshes, materials (PBR metallic-roughness workflow), animations, skins, cameras, light. GLB packages JSON + binary data (geometry, animations) + textures in single file.
Mandatory requirements for Android ARCore / Sceneform:
- Materials only via
pbrMetallicRoughness—Blinn-Phong, Phong, Lambert unsupported - Textures: PNG (with alpha) or JPEG (no alpha), max 2048×2048
- Geometry: triangles only (
TRIANGLESprimitive mode), not quads - No unreferenced nodes and materials (validator complains)
-
asset.generator—recommend setting (helps compatibility debugging)
Converting from Main Formats
FBX → GLB. Blender—best intermediate converter:
blender --background --python fbx_to_glb.py -- input.fbx output.glb
Python script for Blender:
import bpy
bpy.ops.import_scene.fbx(filepath=input_path)
bpy.ops.export_scene.gltf(
filepath=output_path,
export_format='GLB',
export_materials='EXPORT',
export_animations=True,
export_apply=True # applies modifiers
)
Main FBX → GLB problem via Blender: FBX materials often use Standard or Lambert shaders—Blender converts to Principled BSDF, but parameters (specular, shininess) map approximately. Results need visual verification.
OBJ → GLB. OBJ doesn't support animation, PBR materials (only MTL with Kd/Ks), skins. For static objects—convert via Blender or obj2gltf:
obj2gltf -i model.obj -o model.glb
MTL maps to glTF pbrMetallicRoughness approximately: Kd → baseColorFactor, map_Kd → baseColorTexture. Normal, roughness, metallic maps from MTL not picked up—add manually via glTF pipeline.
USDZ → GLB (iOS → Android). Apple Reality Converter can export to USD/OBJ, then via Blender to GLB. No direct USDZ→GLB converter—mandatory intermediate step via USD Python API or Blender.
Optimizing GLB for Mobile AR
Draco compression. Compresses geometry 60–90% without visible quality loss:
npx gltf-pipeline -i model.glb -o model_draco.glb --draco.compressionLevel 7
Important: ARCore supports Draco. Old Three.js without DracoLoader—no. Check compatibility with target renderer.
KTX2/Basis Universal textures. GPU-compressed textures, load faster, use less VRAM:
npx gltf-transform etc1s model.glb model_ktx2.glb
# or toktx for creating KTX2 files separately
Basis Universal decodes on GPU—no RAM unpacking. On Android AR, reduces memory 40–60% for textured models.
Mesh quantization. Pack float32 vertex coordinates to int16—precision loss < 0.01%, size 25–40% gain:
npx gltf-transform quantize model.glb model_quantized.glb
Validation
glTF Validator from Khronos—mandatory before deploy:
npx gltf-validator model.glb
Outputs errors and warnings with codes. Codes like ACCESSOR_ELEMENT_OUT_OF_MIN_BOUND—floating-point values outside allowed range, often from FBX conversion.
model-viewer (Google)—browser glTF viewer, shows model as in ARCore. Ideal for quick verification before device install.
Typical Errors
- Model without UV unwrap—in ARCore white or gray
- Double-sided materials not explicitly set (
doubleSided: truein JSON)—inner faces invisible - Coordinates in inches/centimeters instead of meters—object in AR microscopic or gigantic
- Animation with non-linear interpolation—glTF supports only LINEAR and STEP/CUBICSPLINE
Timeline
| Volume | Timeline |
|---|---|
| 1–10 models with manual conversion and verification | 1–3 days |
| Automated FBX/OBJ → GLB pipeline | 1 week |
| Pack 50–200 models with optimization and validation | 2–3 weeks |
Cost calculated based on volume and source formats.







