Field Guides

How to Batch-Optimize GLB Assets Safely

Build a deterministic GLB optimization pipeline with manifests, per-role profiles, isolated stages, validation, visual regression, concurrency control, and atomic publishing.

Batch optimization turns a useful one-file technique into production infrastructure. It can also multiply one bad assumption across an entire catalog. A script that blindly decimates every mesh, resizes every texture to 1024, and overwrites its input may finish quickly while destroying labels, animation, UVs, attribution, and the only editable source.

A safe pipeline is deterministic, profile-driven, observable, reversible, and strict about validation. It separates mechanical transforms from visual judgment and never publishes partial results.

Define the batch contract#

Write supported inputs and outputs before choosing tools. Record runtime versions, allowed glTF extensions, target platforms, asset roles, quality tiers, and which content features the pipeline supports.

For each profile define:

  • maximum output bytes;
  • geometry and runtime vertex targets;
  • image dimensions and texture encoding;
  • material and primitive limits;
  • animation and skin policies;
  • allowed and required extensions;
  • dimension and transform tolerance;
  • visual comparison cameras;
  • target-device performance threshold;
  • publish destination and rollback behavior.

Do not use one profile for a 2-centimeter ring, a 2-meter sofa, and a background rock. Role metadata should select an appropriate profile or stop the job for review.

Version the contract. An artifact built with web-product-v3 must remain reproducible after web-product-v4 changes quantization or texture quality.

Create an immutable input manifest#

Discover files with a deterministic traversal and stable ordering. For every input record a relative asset ID, source path, byte size, content hash, modification time for diagnostics, license or attribution reference, requested profile, and expected dimensions.

Hash content rather than trusting file names. Two catalog entries called model.glb can contain different bytes; two copies with different names can be identical and reuse work.

Reject duplicate output IDs, missing profile metadata, path traversal, unsupported file types, and source paths inside the output directory. Never follow arbitrary symbolic links in an untrusted batch.

Store the manifest before transforms begin. It becomes the input ledger, cache key foundation, and audit trail.

Preflight every GLB#

Run the Khronos glTF Validator and a structural inspector. Report scenes, nodes, meshes, primitives, accessors, attributes, triangles, vertices, materials, images, animations, skins, morphs, dimensions, transforms, extensions, and component bytes.

Classify validation results:

  • fatal format errors: reject;
  • unsupported required extension: reject;
  • non-finite value or invalid bounds: reject;
  • fixable source hygiene warning: quarantine or route to an explicit repair stage;
  • known reviewed warning: continue with a recorded exception;
  • performance budget warning: process but require final gate.

Do not let an optimizer normalize a malformed source silently. A successful output would hide the upstream defect and make future reconstruction harder.

Extract poster renders or fixed diagnostic views when the asset has approved camera metadata. If no usable view contract exists, mark the result as requiring human review.

Separate lossless and lossy stages#

Run safe structural work first: prune unused resources, deduplicate exact matches, remove empty nodes when semantics allow, normalize layout, and optimize vertex/cache ordering. Validate and report the result.

Run lossy operations in named stages:

  1. attribute quantization;
  2. geometry simplification;
  3. animation key reduction;
  4. texture resize and channel processing;
  5. texture encoding;
  6. geometry compression;
  7. final container packaging.

Write each stage to an isolated temporary directory with its own metrics. This increases storage during a run but makes failures explainable. Production can retain only selected artifacts after reports are complete.

Never repeatedly apply lossy stages to last week's delivery. Rebuild from the immutable source or a designated lossless intermediate.

Use profile-driven geometry decisions#

Automatic simplification needs protected features and a target derived from role metadata. Preserve borders, seams, normals, materials, skinning, and morphs according to the tool and asset.

Skip or quarantine features the pipeline cannot verify. A skinned face with 52 morph targets should not pass through a static-prop simplifier. A CAD model with many separate named parts may require semantic preservation even if merging would reduce draws.

Generate candidates rather than one irreversible answer. A profile can request 50%, 25%, and 12.5% triangle candidates, render them at approved cameras, and choose the smallest passing automated threshold for human confirmation.

Record source and output triangles, runtime vertices, primitive counts, attribute sets, bounds, and simplifier error. A 70% triangle reduction paired with a 40% vertex increase is a warning that seams or attributes changed.

Process textures by semantics#

Identify base color, emissive, normal, metallic, roughness, occlusion, and other data from material references—not file-name guesses alone. Apply color-aware encoding to color signals and data-safe handling to scalar and normal inputs.

Determine target dimensions from the profile, source aspect ratio, UV coverage, and any protected text or label metadata. Do not stretch a 2048 × 1024 image into a square. Remove opaque alpha only after proving it is constant.

Use KTX 2.0, WebP, JPEG, PNG, or other formats according to the runtime contract. If KHR_texture_basisu becomes required, confirm the loader has a configured transcoder. Store encoder versions and all quality settings.

Limit concurrent image encoders by memory. Ten 8192 × 8192 RGBA inputs can require more than 2.5 GiB for only one decoded copy each. A process pool sized to CPU cores can exhaust RAM before it improves throughput.

Make execution deterministic#

Pin tool versions, container or runtime versions, locale, thread settings where they affect output, and profile configuration. Use stable asset ordering and stable JSON serialization. Avoid timestamps inside content-hashed artifacts.

Capture the complete command and environment fingerprint without logging secrets. Resolve executable versions at startup and fail if they differ from the approved lock.

Use a cache key built from source hash, profile version, pipeline code version, and tool versions. A cache hit should return the same report and artifact hash. Never key only on source file modification time.

Test determinism by running a sample batch twice on clean directories. If hashes differ, identify whether the difference is semantic, container ordering, encoder nondeterminism, or embedded metadata.

Bound concurrency and resources#

Use separate limits for CPU-heavy geometry work, memory-heavy texture work, and I/O. Backpressure the input queue instead of loading every GLB into memory.

For example, a 16-core build host with 32 GiB RAM might run 6 geometry tasks, 2 large texture tasks, and 4 validation tasks—not 16 of each. Measure peak resident memory and throughput on representative assets.

Set per-asset timeouts and output-size ceilings. Capture exit code, standard error, stage duration, and peak memory. Kill the process group on timeout so child encoders do not continue writing.

One asset failure should produce a quarantined report and allow unrelated assets to continue when policy permits. The overall release must still fail if any required asset lacks a passing output.

Validate after every structural change#

Protect secrets and untrusted inputs#

Treat batch assets as untrusted data. Run parsers and encoders with least privilege, bounded paths, no production credentials, and restricted network access when feasible. A model should not be able to reference an arbitrary local file or make the worker upload unrelated workspace content.

Pass storage credentials through the job environment or workload identity, never through command strings written into reports. Redact signed URLs and tokens from logs. Validate all resolved paths remain inside the run directory before reading or deleting.

Separate the transform worker from the publisher. The former needs source read and staging write; only the latter needs permission to create immutable release artifacts and move a manifest pointer. This reduces the damage from a malformed tool input or compromised dependency.

Scan dependency updates in a disposable golden run before promotion. Compare output hashes, validation, visual reports, and resource peaks; a patch release in an image codec can change results even when pipeline code is unchanged.

Run the glTF validator after stages that rewrite structure or extensions, and always on the final artifact. Compare preflight and output reports.

Gate:

  • output exists and is within 1 byte and configured ceiling;
  • no validation errors;
  • extensions are inside the allowlist;
  • dimensions and bounds remain within tolerance;
  • required nodes, materials, animations, and semantics remain;
  • triangle, vertex, primitive, and image budgets pass;
  • images decode and meet dimensions;
  • animation durations remain within tolerance;
  • no non-finite transforms or accessors appear;
  • final hash and metrics are recorded.

Do not infer success from a zero process exit code. Tools can complete while producing an artifact that violates the delivery profile.

Add visual regression#

Render source and output from fixed cameras in a pinned reference renderer. Use identical transforms, lighting, tone mapping, resolution, and background. Capture base-color or unlit, normal, depth, silhouette, and production-lit passes when useful.

Compute image differences, silhouette intersection-over-union, depth error, or a perceptual metric. Use thresholds to route results, not to replace human approval. Transparent objects, fine patterns, and animation often need manual review.

Create contact sheets showing source, output, difference heatmap, size change, triangle change, and warning summary. A reviewer should not need to open 9 tools to understand one candidate.

Require human sign-off for new asset roles, large reductions, skinned or morphing assets, legal or attribution changes, and any result near a threshold.

Use atomic publishing#

Write outputs under a run-specific staging prefix. Upload or copy them with content-hashed names, verify bytes and hashes, then publish a manifest pointer only after the entire required set passes.

Never update the live catalog one file at a time. If asset 37 of 40 fails, customers should continue receiving the previous complete release rather than a mixture.

Keep the previous manifest available for rollback. The publishing record should include run ID, Git revision, profile versions, source and output hashes, approvals, and time.

Separate cleanup from publishing. Temporary-stage deletion should not be able to reach immutable sources or current live artifacts.

Report outcomes that teams can act on#

Produce machine-readable JSON and a concise human report. Include totals and distributions, not just a success count.

Useful batch metrics include:

  • inputs, passed, failed, quarantined, skipped, and cache hits;
  • source and output bytes with percentage reduction;
  • geometry and image byte changes;
  • triangles, vertices, primitives, and materials before and after;
  • validation and visual-regression failures by class;
  • stage p50, p95, and maximum duration;
  • peak memory and worker utilization;
  • artifact and report URLs;
  • review owner and exception status;
  • previous release and rollback pointer.

If 30 assets shrink 60% but 4 grow after KTX encoding, make those 4 visible. Aggregate success can hide a broken profile for one material class.

Test the pipeline itself#

Maintain fixtures for static opaque, transparent, skinned, animated, morphing, multi-scene, instanced, compressed, quantized, large-texture, malformed, and intentionally unsupported GLBs.

Test empty batches, duplicate IDs, cancellation, timeout, disk-full behavior, partial upload, cache corruption, tool crash, validation failure, and rollback. Verify that no failure overwrites a source or moves the live manifest.

Run a small golden batch on every pipeline change. Review expected hashes or explained metric differences. Run periodic physical-device tests because structural and rendered regression cannot fully predict decode, GPU, or driver behavior.

Batch pipeline checklist#

  • Profiles are role-specific, versioned, and connected to runtime support.
  • Inputs, provenance, hashes, and output IDs are immutable and collision-free.
  • Preflight rejects invalid or unsupported content explicitly.
  • Lossless and lossy stages are isolated and observable.
  • Geometry and texture operations use semantic metadata.
  • Tools, settings, ordering, cache keys, and environments are deterministic.
  • CPU, memory, I/O, timeout, and output limits bound every worker.
  • Structural, budget, dimension, animation, and extension gates run on outputs.
  • Fixed visual regression routes uncertain results to human review.
  • Content-hashed artifacts publish atomically through a release manifest.
  • Reports expose reductions, failures, timings, and exceptions per asset.
  • Golden fixtures, failure injection, rollback, and device tests cover the pipeline.

Sources and further reading#

Batch optimization should make decisions repeatable, not invisible. Preserve sources, select versioned profiles from asset roles, constrain every stage, validate structure and appearance, and move one complete manifest into production only after every required artifact earns a passing report.

Keep learning

Related guides

Field Guides12 min

The Production 3D Asset Optimization Checklist

Use a complete release checklist for source preservation, geometry, shading, textures, animation, compression, accessibility, SEO, delivery, profiling, and rollback.

3d optimizationrelease checklistGLB
Field Guides10 min

How to Reduce a 20 MB GLB to Under 1 MB

Use an evidence-driven geometry, texture, structure, and compression workflow to shrink a large GLB below 1 MB without approving invisible damage.

GLB optimizationfile sizemesh compression
Field Guides12 min

Preparing a 3D Model for Printing: Manifold Geometry, Wall Thickness, and Watertight Meshes

Learn what makes a mesh physically printable: watertight manifold geometry, consistent normals, merged shells, real wall thickness, and correct scale.

3d printingmanifold geometrywatertight mesh