Simplifying GLB files for use in Unity

Valéry Raulet
5 min readFeb 21, 2023

--

Wireframe of a pumpkin in Blender

GLB file format is convenient as it contains all the files required for rendering including the textures. However, depending on the usage you may want to simplify the file as it is sometimes very detailed.

In this article, I will use gltf-transform to perform the simplification and I will assume you are using Windows.

Installation

To install gltf-transform, you need Node.js. Node.js is a JavaScript runtime environment used by many websites and tools. You can download it from https://nodejs.org/en/. Unless you have a specific need, use the LTS version.

During the installation, accept the defaults as they will be sufficient for what we are doing.

Now, we need to install the tool itself, open a terminal and type:

npm install --global @gltf-transform/cli
Installing gltf-transform/cli

If you get warnings, it should be safe to ignore those.

Inspecting a GLB file

The first action is to inspect the GLB file by typing the following:

C:\pumpkin>gltf-transform inspect file.glb

You will get detailed information about the content of the GLB file such as meshes and textures:


MESHES
────────────────────────────────────────────
┌───┬────────────┬───────────┬────────────┬──────────────┬──────────┬─────────┬──────────────────────────────────────────┬───────────┬───────────┐
│ # │ name │ mode │ primitives │ glPrimitives │ vertices │ indices │ attributes │ instances │ size¹ │
├───┼────────────┼───────────┼────────────┼──────────────┼──────────┼─────────┼──────────────────────────────────────────┼───────────┼───────────┤
│ 0 │ Circle │ TRIANGLES │ 1 │ 21,496 │ 11,916 │ u16 │ NORMAL:f32, POSITION:f32, TEXCOORD_0:f32 │ 1 │ 510.29 KB │
├───┼────────────┼───────────┼────────────┼──────────────┼──────────┼─────────┼──────────────────────────────────────────┼───────────┼───────────┤
│ 1 │ Circle.001 │ TRIANGLES │ 1 │ 10,400 │ 5,560 │ u16 │ NORMAL:f32, POSITION:f32, TEXCOORD_0:f32 │ 1 │ 240.32 KB │
├───┼────────────┼───────────┼────────────┼──────────────┼──────────┼─────────┼──────────────────────────────────────────┼───────────┼───────────┤
│ 2 │ Circle.003 │ TRIANGLES │ 1 │ 8,040 │ 4,207 │ u16 │ NORMAL:f32, POSITION:f32, TEXCOORD_0:f32 │ 1 │ 182.86 KB │
└───┴────────────┴───────────┴────────────┴──────────────┴──────────┴─────────┴──────────────────────────────────────────┴───────────┴───────────┘

TEXTURES
────────────────────────────────────────────
┌───┬────────────────────────────────────────────┬─────┬──────────────────────────┬───────────┬───────────┬─────────────┬────────────┬──────────┬──────────┐
│ # │ name │ uri │ slots │ instances │ mimeType │ compression │ resolution │ size │ gpuSize¹ │
├───┼────────────────────────────────────────────┼─────┼──────────────────────────┼───────────┼───────────┼─────────────┼────────────┼──────────┼──────────┤
│ 0 │ pumpkin_Normal │ │ normalTexture │ 2 │ image/png │ │ 4096x4096 │ 15.3 MB │ 89.48 MB │
├───┼────────────────────────────────────────────┼─────┼──────────────────────────┼───────────┼───────────┼─────────────┼────────────┼──────────┼──────────┤
│ 1 │ pumpkin_Base_Color │ │ baseColorTexture │ 2 │ image/png │ │ 4096x4096 │ 19.78 MB │ 89.48 MB │
├───┼────────────────────────────────────────────┼─────┼──────────────────────────┼───────────┼───────────┼─────────────┼────────────┼──────────┼──────────┤
│ 2 │ pumpkin_Metallic-pumpkin_Roughness │ │ metallicRoughnessTexture │ 1 │ image/png │ │ 4096x4096 │ 19.32 MB │ 89.48 MB │
├───┼────────────────────────────────────────────┼─────┼──────────────────────────┼───────────┼───────────┼─────────────┼────────────┼──────────┼──────────┤
│ 3 │ pumpkin_Metallic.png-pumpkin_Roughness.png │ │ metallicRoughnessTexture │ 1 │ image/png │ │ 4096x4096 │ 19.32 MB │ 89.48 MB │
└───┴────────────────────────────────────────────┴─────┴──────────────────────────┴───────────┴───────────┴─────────────┴────────────┴──────────┴──────────┘

In this example, we have 3 meshes with 11,916, 5,560, and 4,207 vertices. We also have 4 texture images with a resolution of 4096x4096 with a total size of more than 70 MB.

Resize GLB Textures

I don’t need such a detailed texture so I am going to resize its texture files:

C:\pumpkin>gltf-transform resize --width 1024 --height 1024 file.glb file2.glb
info: file.glb (74.65 MB) → file2.glb (6.35 MB)

Here, I decide to use a resolution of 1024x1024 which is more than enough for my need. That means a 8-time reduction in resolution.

Note that the resulting file is more than 10 times smaller (6.25 MB vs 74.65 MB).

Simplify GLB Mesh

With more than 21,000 vertices, this object is too detailed for my use. So, I also want to simplify the mesh:

C:\pumpkin>gltf-transform simplify --ratio 0.25 file2.glb file3.glb
info: file2.glb (6.35 MB) → file3.glb (5.8 MB)

The ratio parameter allows being more or less aggressive in the removal of vertices:

C:\pumpkin>gltf-transform inspect file3.glb

MESHES
────────────────────────────────────────────
┌───┬────────────┬───────────┬────────────┬──────────────┬──────────┬─────────┬──────────────────────────────────────────┬───────────┬───────────┐
│ # │ name │ mode │ primitives │ glPrimitives │ vertices │ indices │ attributes │ instances │ size¹ │
├───┼────────────┼───────────┼────────────┼──────────────┼──────────┼─────────┼──────────────────────────────────────────┼───────────┼───────────┤
│ 0 │ Circle │ TRIANGLES │ 1 │ 9,614 │ 5,550 │ u16 │ NORMAL:f32, POSITION:f32, TEXCOORD_0:f32 │ 1 │ 235.28 KB │
├───┼────────────┼───────────┼────────────┼──────────────┼──────────┼─────────┼──────────────────────────────────────────┼───────────┼───────────┤
│ 1 │ Circle.001 │ TRIANGLES │ 1 │ 3,260 │ 1,886 │ u16 │ NORMAL:f32, POSITION:f32, TEXCOORD_0:f32 │ 1 │ 79.91 KB │
├───┼────────────┼───────────┼────────────┼──────────────┼──────────┼─────────┼──────────────────────────────────────────┼───────────┼───────────┤
│ 2 │ Circle.003 │ TRIANGLES │ 1 │ 2,874 │ 1,543 │ u16 │ NORMAL:f32, POSITION:f32, TEXCOORD_0:f32 │ 1 │ 66.62 KB │
└───┴────────────┴───────────┴────────────┴──────────────┴──────────┴─────────┴──────────────────────────────────────────┴───────────┴───────────┘

It is based on meshoptimizer and you can get more information here:

Other Functions

There are many other functions available with gltf-transform. You can get the list of functions here:

And for any function, you can use the --help parameter to get the list of available parameters:

C:\pumpkin>gltf-transform simplify --help

cli.js 3.0.1 — Command-line interface (CLI) for the glTF Transform SDK.

USAGE — simplify

▸ cli.js simplify <input> <output> [OPTIONS...]


Simplify mesh, reducing number of vertices.

Simplification algorithm producing meshes with fewer triangles and
vertices. Simplification is lossy, but the algorithm aims to
preserve visual quality as much as possible, for given parameters.

The algorithm aims to reach the target --ratio, while minimizing error. If
error exceeds the specified --error threshold, the algorithm will quit
before reaching the target ratio. Examples:

- ratio=0.5, error=0.001: Aims for 50% simplification, constrained to 0.1% error.
- ratio=0.5, error=1: Aims for 50% simplification, unconstrained by error.
- ratio=0.0, error=0.01: Aims for maximum simplification, constrained to 1% error.

Topology, particularly split vertices, will also limit the simplifier. For
best results, apply a 'weld' operation before simplification.

Based on the meshoptimizer library (https://github.com/zeux/meshoptimizer).


ARGUMENTS

<input> Path to read glTF 2.0 (.glb, .gltf) model
<output> Path to write output

OPTIONS

--error <error> Limit on error, as a fraction of mesh radius
number, default: 0.001
--lock-border <lockBorder> Whether to lock topological borders of the mesh
boolean
--ratio <ratio> Target ratio (0–1) of vertices to keep
number, default: 0.5

Result

We can see a loss of details in the result but obviously, it depends on how you want to use your GLB file:

Original GLB (left) and optimized GLB (right)

--

--

Valéry Raulet
Valéry Raulet

Written by Valéry Raulet

I have been interested in business and technology since I was about 10. My interest spans across so many fields but I hope you’ll find my writing useful!

No responses yet